This revision was automatically updated to reflect the committed changes.
Closed by commit rL259644: Add ability to override JIT expr compiler options. 
(authored by aidandodds).

Changed prior to commit:
  http://reviews.llvm.org/D15527?vs=45588&id=46769#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D15527

Files:
  lldb/trunk/include/lldb/Target/LanguageRuntime.h
  lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp

Index: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
===================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -64,6 +64,7 @@
 #include "lldb/Core/Module.h"
 #include "lldb/Core/Stream.h"
 #include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StringList.h"
 #include "lldb/Core/StreamString.h"
 #include "lldb/Expression/IRExecutionUnit.h"
 #include "lldb/Expression/IRDynamicChecks.h"
@@ -76,6 +77,7 @@
 #include "lldb/Target/ObjCLanguageRuntime.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/Target.h"
+#include "lldb/Target/Language.h"
 
 using namespace clang;
 using namespace llvm;
@@ -166,55 +168,106 @@
     m_code_generator (),
     m_pp_callbacks(nullptr)
 {
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
     // 1. Create a new compiler instance.
     m_compiler.reset(new CompilerInstance());
-
-    // 2. Install the target.
-
+    lldb::LanguageType frame_lang = expr.Language(); // defaults to lldb::eLanguageTypeUnknown
+    bool overridden_target_opts = false;
+    lldb_private::LanguageRuntime *lang_rt = nullptr;
     lldb::TargetSP target_sp;
     if (exe_scope)
         target_sp = exe_scope->CalculateTarget();
 
-    // TODO: figure out what to really do when we don't have a valid target.
-    // Sometimes this will be ok to just use the host target triple (when we
-    // evaluate say "2+3", but other expressions like breakpoint conditions
-    // and other things that _are_ target specific really shouldn't just be
-    // using the host triple. This needs to be fixed in a better way.
+    // If the expression is being evaluated in the context of an existing
+    // stack frame, we introspect to see if the language runtime is available.
+    auto frame = exe_scope->CalculateStackFrame();
+
+    // Make sure the user hasn't provided a preferred execution language
+    // with `expression --language X -- ...`
+    if (frame && frame_lang == lldb::eLanguageTypeUnknown)
+        frame_lang = frame->GetLanguage();
+
+    if (frame_lang != lldb::eLanguageTypeUnknown)
+    {
+        lang_rt = exe_scope->CalculateProcess()->GetLanguageRuntime(frame_lang);
+        if (log)
+            log->Printf("Frame has language of type %s", Language::GetNameForLanguageType(frame_lang));
+    }
+
+    // 2. Configure the compiler with a set of default options that are appropriate
+    // for most situations.
     if (target_sp && target_sp->GetArchitecture().IsValid())
     {
         std::string triple = target_sp->GetArchitecture().GetTriple().str();
         m_compiler->getTargetOpts().Triple = triple;
+        if (log)
+            log->Printf("Using %s as the target triple", m_compiler->getTargetOpts().Triple.c_str());
     }
     else
     {
+        // If we get here we don't have a valid target and just have to guess.
+        // Sometimes this will be ok to just use the host target triple (when we evaluate say "2+3", but other
+        // expressions like breakpoint conditions and other things that _are_ target specific really shouldn't just be
+        // using the host triple. In such a case the language runtime should expose an overridden options set (3),
+        // below.
         m_compiler->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple();
+        if (log)
+            log->Printf("Using default target triple of %s", m_compiler->getTargetOpts().Triple.c_str());
     }
-
-    if (target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86 ||
-        target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86_64)
-    {
-        m_compiler->getTargetOpts().Features.push_back("+sse");
-        m_compiler->getTargetOpts().Features.push_back("+sse2");
-    }
-
+    // Now add some special fixes for known architectures:
     // Any arm32 iOS environment, but not on arm64
     if (m_compiler->getTargetOpts().Triple.find("arm64") == std::string::npos &&
         m_compiler->getTargetOpts().Triple.find("arm") != std::string::npos &&
         m_compiler->getTargetOpts().Triple.find("ios") != std::string::npos)
     {
         m_compiler->getTargetOpts().ABI = "apcs-gnu";
     }
+    // Supported subsets of x86
+    if (target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86 ||
+        target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86_64)
+    {
+        m_compiler->getTargetOpts().Features.push_back("+sse");
+        m_compiler->getTargetOpts().Features.push_back("+sse2");
+    }
 
-    m_compiler->createDiagnostics();
+    // 3. Now allow the runtime to provide custom configuration options for the target.
+    // In this case, a specialized language runtime is available and we can query it for extra options.
+    // For 99% of use cases, this will not be needed and should be provided when basic platform detection is not enough.
+    if (lang_rt)
+        overridden_target_opts = lang_rt->GetOverrideExprOptions(m_compiler->getTargetOpts());
 
-    // Create the target instance.
-    m_compiler->setTarget(TargetInfo::CreateTargetInfo(
-        m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts));
+    if (overridden_target_opts)
+        if (log)
+        {
+            log->Debug("Using overridden target options for the expression evaluation");
 
-    assert (m_compiler->hasTarget());
+            auto opts = m_compiler->getTargetOpts();
+            log->Debug("Triple: '%s'", opts.Triple.c_str());
+            log->Debug("CPU: '%s'", opts.CPU.c_str());
+            log->Debug("FPMath: '%s'", opts.FPMath.c_str());
+            log->Debug("ABI: '%s'", opts.ABI.c_str());
+            log->Debug("LinkerVersion: '%s'", opts.LinkerVersion.c_str());
+            StringList::LogDump(log, opts.FeaturesAsWritten, "FeaturesAsWritten");
+            StringList::LogDump(log, opts.Features, "Features");
+            StringList::LogDump(log, opts.Reciprocals, "Reciprocals");
+        }
+
+    // 4. Create and install the target on the compiler.
+    m_compiler->createDiagnostics();
+    auto target_info = TargetInfo::CreateTargetInfo(m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts);
+    if (log)
+    {
+        log->Printf("Using SIMD alignment: %d", target_info->getSimdDefaultAlign());
+        log->Printf("Target datalayout string: '%s'", target_info->getDataLayoutString());
+        log->Printf("Target ABI: '%s'", target_info->getABI().str().c_str());
+        log->Printf("Target vector alignment: %d", target_info->getMaxVectorAlign());
+    }
+    m_compiler->setTarget(target_info);
 
-    // 3. Set options.
+    assert (m_compiler->hasTarget());
 
+    // 5. Set language options.
     lldb::LanguageType language = expr.Language();
 
     switch (language)
@@ -321,11 +374,11 @@
     // created. This complexity should be lifted elsewhere.
     m_compiler->getTarget().adjust(m_compiler->getLangOpts());
 
-    // 4. Set up the diagnostic buffer for reporting errors
+    // 6. Set up the diagnostic buffer for reporting errors
 
     m_compiler->getDiagnostics().setClient(new clang::TextDiagnosticBuffer);
 
-    // 5. Set up the source management objects inside the compiler
+    // 7. Set up the source management objects inside the compiler
 
     clang::FileSystemOptions file_system_options;
     m_file_manager.reset(new clang::FileManager(file_system_options));
@@ -344,7 +397,7 @@
         m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks));
     }
         
-    // 6. Most of this we get from the CompilerInstance, but we
+    // 8. Most of this we get from the CompilerInstance, but we
     // also want to give the context an ExternalASTSource.
     m_selector_table.reset(new SelectorTable());
     m_builtin_context.reset(new Builtin::Context());
Index: lldb/trunk/include/lldb/Target/LanguageRuntime.h
===================================================================
--- lldb/trunk/include/lldb/Target/LanguageRuntime.h
+++ lldb/trunk/include/lldb/Target/LanguageRuntime.h
@@ -22,6 +22,7 @@
 #include "lldb/Core/ValueObject.h"
 #include "lldb/Core/Value.h"
 #include "lldb/Target/ExecutionContextScope.h"
+#include "clang/Basic/TargetOptions.h"
 
 namespace lldb_private {
 
@@ -147,6 +148,15 @@
     {
     }
 
+    // Called by the Clang expression evaluation engine to allow runtimes to alter the set of target options provided to
+    // the compiler.
+    // If the options prototype is modified, runtimes must return true, false otherwise.
+    virtual bool
+    GetOverrideExprOptions(clang::TargetOptions &prototype)
+    {
+        return false;
+    }
+
 protected:
     //------------------------------------------------------------------
     // Classes that inherit from LanguageRuntime can see and modify these
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to