New settings: target.use-hex-immediates and target.hex-immediates-style
- Immediates can be shown as hex (either Intel or MASM style)
- See TestSettings.py for usage examples
- Verified to cause no regressions on Linux x86_64 (Ubuntu 12.10)

Patch by Richard Mitton!



git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@187921 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/lldb/Core/Disassembler.h b/include/lldb/Core/Disassembler.h
index 9a027e6..d6e9007 100644
--- a/include/lldb/Core/Disassembler.h
+++ b/include/lldb/Core/Disassembler.h
@@ -248,6 +248,12 @@
         eOptionMarkPCAddress    = (1u << 3)  // Mark the disassembly line the contains the PC
     };
 
+    enum HexImmediateStyle
+    {
+        eHexStyleC,
+        eHexStyleAsm,
+    };
+
     // FindPlugin should be lax about the flavor string (it is too annoying to have various internal uses of the
     // disassembler fail because the global flavor string gets set wrong.  Instead, if you get a flavor string you
     // don't understand, use the default.  Folks who care to check can use the FlavorValidForArchSpec method on the
diff --git a/include/lldb/Target/Target.h b/include/lldb/Target/Target.h
index 33effa1..d86ef26 100644
--- a/include/lldb/Target/Target.h
+++ b/include/lldb/Target/Target.h
@@ -22,6 +22,7 @@
 #include "lldb/Breakpoint/WatchpointList.h"
 #include "lldb/Core/ArchSpec.h"
 #include "lldb/Core/Broadcaster.h"
+#include "lldb/Core/Disassembler.h"
 #include "lldb/Core/Event.h"
 #include "lldb/Core/ModuleList.h"
 #include "lldb/Core/UserSettingsController.h"
@@ -46,14 +47,14 @@
     eInlineBreakpointsHeaders,
     eInlineBreakpointsAlways
 } InlineStrategy;
-    
+
 typedef enum LoadScriptFromSymFile
 {
     eLoadScriptFromSymFileTrue,
     eLoadScriptFromSymFileFalse,
     eLoadScriptFromSymFileWarn
 } LoadScriptFromSymFile;
-    
+
 //----------------------------------------------------------------------
 // TargetProperties
 //----------------------------------------------------------------------
@@ -157,13 +158,19 @@
     
     const char *
     GetExpressionPrefixContentsAsCString ();
-    
+
+    bool
+    GetUseHexImmediates() const;
+
     bool
     GetUseFastStepping() const;
-    
+
     LoadScriptFromSymFile
     GetLoadScriptFromSymbolFile() const;
-    
+
+    Disassembler::HexImmediateStyle
+    GetHexImmediateStyle() const;
+
 };
 
 typedef std::shared_ptr<TargetProperties> TargetPropertiesSP;
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
index 233515a..e920d70 100644
--- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
+++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
@@ -256,12 +256,18 @@
             m_using_file_addr = true;
             
             const bool data_from_file = GetDisassemblerLLVMC().m_data_from_file;
-            if (!data_from_file)
+            bool use_hex_immediates = true;
+            Disassembler::HexImmediateStyle hex_style = Disassembler::eHexStyleC;
+
+            if (exe_ctx)
             {
-                if (exe_ctx)
+                Target *target = exe_ctx->GetTargetPtr();
+                if (target)
                 {
-                    Target *target = exe_ctx->GetTargetPtr();
-                    if (target)
+                    use_hex_immediates = target->GetUseHexImmediates();
+                    hex_style = target->GetHexImmediateStyle();
+
+                    if (!data_from_file)
                     {
                         const lldb::addr_t load_addr = m_address.GetLoadAddress(target);
                         if (load_addr != LLDB_INVALID_ADDRESS)
@@ -282,10 +288,13 @@
                                                          opcode_data_len,
                                                          pc,
                                                          inst);
-                
+
             if (inst_size > 0)
+            {
+                mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style);
                 mc_disasm_ptr->PrintMCInst(inst, out_string, sizeof(out_string));
-            
+            }
+
             llvm_disasm.Unlock();
             
             if (inst_size == 0)
@@ -546,6 +555,17 @@
     return output_size;
 }
 
+void
+DisassemblerLLVMC::LLVMCDisassembler::SetStyle (bool use_hex_immed, HexImmediateStyle hex_style)
+{
+    m_instr_printer_ap->setPrintImmHex(use_hex_immed);
+    switch(hex_style)
+    {
+    case eHexStyleC:      m_instr_printer_ap->setPrintImmHex(llvm::HexStyle::C); break;
+    case eHexStyleAsm:    m_instr_printer_ap->setPrintImmHex(llvm::HexStyle::Asm); break;
+    }
+}
+
 bool
 DisassemblerLLVMC::LLVMCDisassembler::CanBranch (llvm::MCInst &mc_inst)
 {
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
index 29b28ad..c567791 100644
--- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
+++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
@@ -47,6 +47,7 @@
         
         uint64_t GetMCInst (const uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc, llvm::MCInst &mc_inst);
         uint64_t PrintMCInst (llvm::MCInst &mc_inst, char *output_buffer, size_t out_buffer_len);
+        void     SetStyle (bool use_hex_immed, HexImmediateStyle hex_style);
         bool     CanBranch (llvm::MCInst &mc_inst);
         bool     IsValid()
         {
@@ -54,7 +55,7 @@
         }
         
     private:
-        bool                                    m_is_valid;
+        bool                                     m_is_valid;
         std::unique_ptr<llvm::MCContext>         m_context_ap;
         std::unique_ptr<llvm::MCAsmInfo>         m_asm_info_ap;
         std::unique_ptr<llvm::MCSubtargetInfo>   m_subtarget_info_ap;
diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp
index c7638e9..70ff046 100644
--- a/source/Target/Target.cpp
+++ b/source/Target/Target.cpp
@@ -2297,6 +2297,14 @@
 };
 
 static OptionEnumValueElement
+g_hex_immediate_style_values[] =
+{
+    { Disassembler::eHexStyleC,        "c",      "C-style (0xffff)."},
+    { Disassembler::eHexStyleAsm,      "asm",    "Asm-style (0ffffh)."},
+    { 0, NULL, NULL }
+};
+
+static OptionEnumValueElement
 g_load_script_from_sym_file_values[] =
 {
     { eLoadScriptFromSymFileTrue,    "true",    "Load debug scripts inside symbol files"},
@@ -2342,6 +2350,8 @@
         "file and line breakpoints." },
     // FIXME: This is the wrong way to do per-architecture settings, but we don't have a general per architecture settings system in place yet.
     { "x86-disassembly-flavor"             , OptionValue::eTypeEnum      , false, eX86DisFlavorDefault,       NULL, g_x86_dis_flavor_value_types, "The default disassembly flavor to use for x86 or x86-64 targets." },
+    { "use-hex-immediates"                 , OptionValue::eTypeBoolean   , false, true,                       NULL, NULL, "Show immediates in disassembly as hexadecimal." },
+    { "hex-immediate-style"                , OptionValue::eTypeEnum   ,    false, Disassembler::eHexStyleC,   NULL, g_hex_immediate_style_values, "Which style to use for printing hexadecimal disassembly values." },
     { "use-fast-stepping"                  , OptionValue::eTypeBoolean   , false, true,                       NULL, NULL, "Use a fast stepping algorithm based on running from branch to branch rather than instruction single-stepping." },
     { "load-script-from-symbol-file"       , OptionValue::eTypeEnum   ,    false, eLoadScriptFromSymFileWarn, NULL, g_load_script_from_sym_file_values, "Allow LLDB to load scripting resources embedded in symbol files when available." },
     { NULL                                 , OptionValue::eTypeInvalid   , false, 0                         , NULL, NULL, NULL }
@@ -2371,6 +2381,8 @@
     ePropertyDisableSTDIO,
     ePropertyInlineStrategy,
     ePropertyDisassemblyFlavor,
+    ePropertyUseHexImmediates,
+    ePropertyHexImmediateStyle,
     ePropertyUseFastStepping,
     ePropertyLoadScriptFromSymbolFile,
 };
@@ -2735,6 +2747,13 @@
 }
 
 bool
+TargetProperties::GetUseHexImmediates () const
+{
+    const uint32_t idx = ePropertyUseHexImmediates;
+    return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+}
+
+bool
 TargetProperties::GetUseFastStepping () const
 {
     const uint32_t idx = ePropertyUseFastStepping;
@@ -2748,6 +2767,13 @@
     return (LoadScriptFromSymFile)m_collection_sp->GetPropertyAtIndexAsEnumeration(NULL, idx, g_properties[idx].default_uint_value);
 }
 
+Disassembler::HexImmediateStyle
+TargetProperties::GetHexImmediateStyle () const
+{
+    const uint32_t idx = ePropertyHexImmediateStyle;
+    return (Disassembler::HexImmediateStyle)m_collection_sp->GetPropertyAtIndexAsEnumeration(NULL, idx, g_properties[idx].default_uint_value);
+}
+
 const TargetPropertiesSP &
 Target::GetGlobalProperties()
 {
diff --git a/test/settings/TestSettings.py b/test/settings/TestSettings.py
index 09a6860..fe75afc 100644
--- a/test/settings/TestSettings.py
+++ b/test/settings/TestSettings.py
@@ -158,6 +158,40 @@
         self.expect("settings show auto-confirm", SETTING_MSG("auto-confirm"),
             startstr = "auto-confirm (boolean) = false")
 
+    @unittest2.skipUnless(os.uname()[4] in ['i386', 'x86_64'], "requires x86 or x86_64")
+    def test_disassembler_settings(self):
+        """Test that user options for the disassembler take effect."""
+        self.buildDefault()
+
+        exe = os.path.join(os.getcwd(), "a.out")
+        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+        # AT&T syntax
+        self.runCmd("settings set target.x86-disassembly-flavor att")
+        self.runCmd("settings set target.use-hex-immediates false")
+        self.expect("disassemble -n numberfn",
+            substrs = ["$90"])
+        self.runCmd("settings set target.use-hex-immediates true")
+        self.runCmd("settings set target.hex-immediate-style c")
+        self.expect("disassemble -n numberfn",
+            substrs = ["$0x5a"])
+        self.runCmd("settings set target.hex-immediate-style asm")
+        self.expect("disassemble -n numberfn",
+            substrs = ["$5ah"])
+
+        # Intel syntax
+        self.runCmd("settings set target.x86-disassembly-flavor intel")
+        self.runCmd("settings set target.use-hex-immediates false")
+        self.expect("disassemble -n numberfn",
+            substrs = ["90"])
+        self.runCmd("settings set target.use-hex-immediates true")
+        self.runCmd("settings set target.hex-immediate-style c")
+        self.expect("disassemble -n numberfn",
+            substrs = ["0x5a"])
+        self.runCmd("settings set target.hex-immediate-style asm")
+        self.expect("disassemble -n numberfn",
+            substrs = ["5ah"])
+
     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     @dsym_test
     def test_run_args_and_env_vars_with_dsym(self):
@@ -390,6 +424,9 @@
                                  "target.error-path",
                                  "target.disable-aslr",
                                  "target.disable-stdio",
+                                 "target.x86-disassembly-flavor",
+                                 "target.use-hex-immediates",
+                                 "target.hex-immediate-style",
                                  "target.process.disable-memory-cache",
                                  "target.process.extra-startup-command",
                                  "target.process.thread.step-avoid-regexp",
diff --git a/test/settings/main.cpp b/test/settings/main.cpp
index 0ceb427..cf2b16b 100644
--- a/test/settings/main.cpp
+++ b/test/settings/main.cpp
@@ -12,6 +12,11 @@
 #include <fstream>
 #include <iostream>
 
+int numberfn()
+{
+    return 0x5a;
+}
+
 int
 main(int argc, char const *argv[])
 {
@@ -66,5 +71,5 @@
     std::cout << "This message should go to standard out.\n";
 
     outfile.close();
-    return 0;
+    return numberfn();
 }