[llvm] r371159 - [MC] Fix undefined behavior in MCInstPrinter::formatHex
Jonas Devlieghere via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 5 18:13:32 PDT 2019
Author: jdevlieghere
Date: Thu Sep 5 18:13:32 2019
New Revision: 371159
URL: http://llvm.org/viewvc/llvm-project?rev=371159&view=rev
Log:
[MC] Fix undefined behavior in MCInstPrinter::formatHex
Passing INT64_MIN to MCInstPrinter::formatHex triggers undefined
behavior because the negation of -9223372036854775808 cannot be
represented in type 'int64_t' (aka 'long long'). This patch puts a
workaround in place to just print the hex value directly.
A possible alternative involves using a small helper functions that uses
(implementation) defined conversions to achieve the desirable value:
static int64_t helper(int64_t V) {
auto U = static_cast<uint64_t>(V);
return V < 0 ? -U : U;
}
The underlying problem is that MCInstPrinter::formatHex(int64_t) returns
a format_object<int64_t> and should really return a
format_object<uint64_t>. However, that's not possible because formatImm
needs to be able to print both as decimal (where a signed is required)
and hex (where we'd prefer to always have an unsigned).
format_object<int64_t> formatImm(int64_t Value) const {
return PrintImmHex ? formatHex(Value) : formatDec(Value);
}
Differential revision: https://reviews.llvm.org/D67236
Added:
llvm/trunk/unittests/MC/MCInstPrinter.cpp
Modified:
llvm/trunk/lib/MC/MCInstPrinter.cpp
llvm/trunk/unittests/MC/CMakeLists.txt
Modified: llvm/trunk/lib/MC/MCInstPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCInstPrinter.cpp?rev=371159&r1=371158&r2=371159&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCInstPrinter.cpp (original)
+++ llvm/trunk/lib/MC/MCInstPrinter.cpp Thu Sep 5 18:13:32 2019
@@ -83,24 +83,25 @@ format_object<int64_t> MCInstPrinter::fo
}
format_object<int64_t> MCInstPrinter::formatHex(int64_t Value) const {
- switch(PrintHexStyle) {
+ switch (PrintHexStyle) {
case HexStyle::C:
- if (Value < 0)
+ if (Value < 0) {
+ if (Value == std::numeric_limits<int64_t>::min())
+ return format<int64_t>("-0x8000000000000000", Value);
return format("-0x%" PRIx64, -Value);
- else
- return format("0x%" PRIx64, Value);
+ }
+ return format("0x%" PRIx64, Value);
case HexStyle::Asm:
if (Value < 0) {
- if (needsLeadingZero((uint64_t)(-Value)))
+ if (Value == std::numeric_limits<int64_t>::min())
+ return format<int64_t>("-8000000000000000h", Value);
+ if (needsLeadingZero(-(uint64_t)(Value)))
return format("-0%" PRIx64 "h", -Value);
- else
- return format("-%" PRIx64 "h", -Value);
- } else {
- if (needsLeadingZero((uint64_t)(Value)))
- return format("0%" PRIx64 "h", Value);
- else
- return format("%" PRIx64 "h", Value);
+ return format("-%" PRIx64 "h", -Value);
}
+ if (needsLeadingZero((uint64_t)(Value)))
+ return format("0%" PRIx64 "h", Value);
+ return format("%" PRIx64 "h", Value);
}
llvm_unreachable("unsupported print style");
}
Modified: llvm/trunk/unittests/MC/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/MC/CMakeLists.txt?rev=371159&r1=371158&r2=371159&view=diff
==============================================================================
--- llvm/trunk/unittests/MC/CMakeLists.txt (original)
+++ llvm/trunk/unittests/MC/CMakeLists.txt Thu Sep 5 18:13:32 2019
@@ -8,6 +8,7 @@ set(LLVM_LINK_COMPONENTS
add_llvm_unittest(MCTests
Disassembler.cpp
DwarfLineTables.cpp
+ MCInstPrinter.cpp
StringTableBuilderTest.cpp
TargetRegistry.cpp
)
Added: llvm/trunk/unittests/MC/MCInstPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/MC/MCInstPrinter.cpp?rev=371159&view=auto
==============================================================================
--- llvm/trunk/unittests/MC/MCInstPrinter.cpp (added)
+++ llvm/trunk/unittests/MC/MCInstPrinter.cpp Thu Sep 5 18:13:32 2019
@@ -0,0 +1,68 @@
+//===- llvm/unittest/MC/MCInstPrinter.cpp ---------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+class MCInstPrinterTest : public ::testing::Test {
+public:
+ std::unique_ptr<MCRegisterInfo> MRI;
+ std::unique_ptr<MCAsmInfo> MAI;
+ std::unique_ptr<const MCInstrInfo> MII;
+ std::unique_ptr<MCInstPrinter> Printer;
+
+ MCInstPrinterTest() {
+ llvm::InitializeAllTargetInfos();
+ llvm::InitializeAllTargetMCs();
+
+ std::string TripleName = "x86_64-pc-linux";
+ std::string ErrorStr;
+
+ const Target *TheTarget =
+ TargetRegistry::lookupTarget(TripleName, ErrorStr);
+
+ // If we didn't build x86, do not run the test.
+ if (!TheTarget)
+ return;
+
+ MRI.reset(TheTarget->createMCRegInfo(TripleName));
+ MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName));
+ MII.reset(TheTarget->createMCInstrInfo());
+ Printer.reset(TheTarget->createMCInstPrinter(
+ Triple(TripleName), MAI->getAssemblerDialect(), *MAI, *MII, *MRI));
+ }
+
+ template <typename T> std::string formatHex(T i) {
+ std::string Buffer;
+ raw_string_ostream OS(Buffer);
+ OS << Printer->formatHex(i);
+ OS.flush();
+ return Buffer;
+ }
+};
+} // namespace
+
+TEST_F(MCInstPrinterTest, formatHex) {
+ if (!Printer)
+ return;
+
+ EXPECT_EQ("0x1", formatHex<int64_t>(1));
+ EXPECT_EQ("0x7fffffffffffffff",
+ formatHex(std::numeric_limits<int64_t>::max()));
+ EXPECT_EQ("-0x8000000000000000",
+ formatHex(std::numeric_limits<int64_t>::min()));
+}
More information about the llvm-commits
mailing list