In #168245, I attempted to dump the available settings to Markdown. That required a full build of LLDB. However, to build the docs, only the swig wrappers should need to be compiled. The comment was that we should be able to use the definitions from the TableGen files. Currently, the property definitions in don't have information about the path where they will be available. They only contain a `Definition` which groups properties, so they can be added to `OptionValueProperties`. With this PR, I'm adding the path for each property definition. For example, `symbols.enable-external-lookup` would have `Name = enable-external-lookup, Path = symbols`. In LLDB itself, we don't need this path, we only need it for the documentation. To avoid mismatches between the actual path and the declared one, I added a debug-only check when a property group is added to a parent (`OptionValueProperties::AppendProperty`). The TableGen emitter for the properties now additionally emits `g_{definition}_properties_def`, which includes both the array of properties and the expected path. This constant has to be used to initialize a `OptionValueProperties`. I couldn't test this for everything (e.g. IntelPT or ProcessKDP), but the necessary changes are simple: (1) set the `Path` in the TableGen file, (2) update `initialize` to use `_def`.
638 lines
19 KiB
C++
638 lines
19 KiB
C++
//===-- Language.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 <functional>
|
|
#include <map>
|
|
#include <mutex>
|
|
|
|
#include "lldb/Target/Language.h"
|
|
|
|
#include "lldb/Core/PluginManager.h"
|
|
#include "lldb/Interpreter/OptionValueProperties.h"
|
|
#include "lldb/Symbol/SymbolFile.h"
|
|
#include "lldb/Symbol/TypeList.h"
|
|
#include "lldb/Target/Target.h"
|
|
#include "lldb/Utility/Stream.h"
|
|
|
|
#include "llvm/BinaryFormat/Dwarf.h"
|
|
#include "llvm/Support/Threading.h"
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
using namespace lldb_private::formatters;
|
|
|
|
typedef std::unique_ptr<Language> LanguageUP;
|
|
typedef std::map<lldb::LanguageType, LanguageUP> LanguagesMap;
|
|
|
|
#define LLDB_PROPERTIES_language
|
|
#include "TargetProperties.inc"
|
|
|
|
enum {
|
|
#define LLDB_PROPERTIES_language
|
|
#include "TargetPropertiesEnum.inc"
|
|
};
|
|
|
|
LanguageProperties &Language::GetGlobalLanguageProperties() {
|
|
static LanguageProperties g_settings;
|
|
return g_settings;
|
|
}
|
|
|
|
llvm::StringRef LanguageProperties::GetSettingName() {
|
|
static constexpr llvm::StringLiteral g_setting_name("language");
|
|
return g_setting_name;
|
|
}
|
|
|
|
LanguageProperties::LanguageProperties() {
|
|
m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
|
|
m_collection_sp->Initialize(g_language_properties_def);
|
|
}
|
|
|
|
bool LanguageProperties::GetEnableFilterForLineBreakpoints() const {
|
|
const uint32_t idx = ePropertyEnableFilterForLineBreakpoints;
|
|
return GetPropertyAtIndexAs<bool>(
|
|
idx, g_language_properties[idx].default_uint_value != 0);
|
|
}
|
|
|
|
static LanguagesMap &GetLanguagesMap() {
|
|
static LanguagesMap *g_map = nullptr;
|
|
static llvm::once_flag g_initialize;
|
|
|
|
llvm::call_once(g_initialize, [] {
|
|
g_map = new LanguagesMap(); // NOTE: INTENTIONAL LEAK due to global
|
|
// destructor chain
|
|
});
|
|
|
|
return *g_map;
|
|
}
|
|
static std::mutex &GetLanguagesMutex() {
|
|
static std::mutex *g_mutex = nullptr;
|
|
static llvm::once_flag g_initialize;
|
|
|
|
llvm::call_once(g_initialize, [] {
|
|
g_mutex = new std::mutex(); // NOTE: INTENTIONAL LEAK due to global
|
|
// destructor chain
|
|
});
|
|
|
|
return *g_mutex;
|
|
}
|
|
|
|
Language *Language::FindPlugin(lldb::LanguageType language) {
|
|
std::lock_guard<std::mutex> guard(GetLanguagesMutex());
|
|
LanguagesMap &map(GetLanguagesMap());
|
|
auto iter = map.find(language), end = map.end();
|
|
if (iter != end)
|
|
return iter->second.get();
|
|
|
|
Language *language_ptr = nullptr;
|
|
LanguageCreateInstance create_callback;
|
|
|
|
for (uint32_t idx = 0;
|
|
(create_callback =
|
|
PluginManager::GetLanguageCreateCallbackAtIndex(idx)) != nullptr;
|
|
++idx) {
|
|
language_ptr = create_callback(language);
|
|
|
|
if (language_ptr) {
|
|
map[language] = std::unique_ptr<Language>(language_ptr);
|
|
return language_ptr;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
Language *Language::FindPlugin(llvm::StringRef file_path) {
|
|
Language *result = nullptr;
|
|
ForEach([&result, file_path](Language *language) {
|
|
if (language->IsSourceFile(file_path)) {
|
|
result = language;
|
|
return IterationAction::Stop;
|
|
}
|
|
return IterationAction::Continue;
|
|
});
|
|
return result;
|
|
}
|
|
|
|
Language *Language::FindPlugin(LanguageType language,
|
|
llvm::StringRef file_path) {
|
|
Language *result = FindPlugin(language);
|
|
// Finding a language by file path is slower, we so we use this as the
|
|
// fallback.
|
|
if (!result)
|
|
result = FindPlugin(file_path);
|
|
return result;
|
|
}
|
|
|
|
void Language::ForEach(
|
|
llvm::function_ref<IterationAction(Language *)> callback) {
|
|
// If we want to iterate over all languages, we first have to complete the
|
|
// LanguagesMap.
|
|
static llvm::once_flag g_initialize;
|
|
llvm::call_once(g_initialize, [] {
|
|
for (unsigned lang = eLanguageTypeUnknown; lang < eNumLanguageTypes;
|
|
++lang) {
|
|
FindPlugin(static_cast<lldb::LanguageType>(lang));
|
|
}
|
|
});
|
|
|
|
// callback may call a method in Language that attempts to acquire the same
|
|
// lock (such as Language::ForEach or Language::FindPlugin). To avoid a
|
|
// deadlock, we do not use callback while holding the lock.
|
|
std::vector<Language *> loaded_plugins;
|
|
{
|
|
std::lock_guard<std::mutex> guard(GetLanguagesMutex());
|
|
LanguagesMap &map(GetLanguagesMap());
|
|
for (const auto &entry : map) {
|
|
if (entry.second)
|
|
loaded_plugins.push_back(entry.second.get());
|
|
}
|
|
}
|
|
|
|
for (auto *lang : loaded_plugins) {
|
|
if (callback(lang) == IterationAction::Stop)
|
|
break;
|
|
}
|
|
}
|
|
|
|
llvm::Expected<LanguageType>
|
|
Language::GetExceptionLanguageForLanguage(llvm::StringRef lang_name) {
|
|
LanguageType language = Language::GetLanguageTypeFromString(lang_name);
|
|
LanguageType exception_language = eLanguageTypeUnknown;
|
|
|
|
llvm::StringRef error_context;
|
|
switch (language) {
|
|
case eLanguageTypeC89:
|
|
case eLanguageTypeC:
|
|
case eLanguageTypeC99:
|
|
case eLanguageTypeC11:
|
|
exception_language = eLanguageTypeC;
|
|
break;
|
|
case eLanguageTypeC_plus_plus:
|
|
case eLanguageTypeC_plus_plus_03:
|
|
case eLanguageTypeC_plus_plus_11:
|
|
case eLanguageTypeC_plus_plus_14:
|
|
exception_language = eLanguageTypeC_plus_plus;
|
|
break;
|
|
case eLanguageTypeObjC_plus_plus:
|
|
error_context =
|
|
"Set exception breakpoints separately for c++ and objective-c";
|
|
break;
|
|
case eLanguageTypeUnknown:
|
|
error_context = "Unknown language type for exception breakpoint";
|
|
break;
|
|
default:
|
|
if (Language *languagePlugin = Language::FindPlugin(language)) {
|
|
if (languagePlugin->SupportsExceptionBreakpointsOnThrow() ||
|
|
languagePlugin->SupportsExceptionBreakpointsOnCatch()) {
|
|
exception_language = language;
|
|
break;
|
|
}
|
|
}
|
|
error_context = "Unsupported language type for exception breakpoint";
|
|
}
|
|
if (!error_context.empty())
|
|
return llvm::createStringError(llvm::inconvertibleErrorCode(),
|
|
error_context);
|
|
return exception_language;
|
|
}
|
|
|
|
bool Language::IsTopLevelFunction(Function &function) { return false; }
|
|
|
|
lldb::TypeCategoryImplSP Language::GetFormatters() { return nullptr; }
|
|
|
|
HardcodedFormatters::HardcodedFormatFinder Language::GetHardcodedFormats() {
|
|
return {};
|
|
}
|
|
|
|
HardcodedFormatters::HardcodedSummaryFinder Language::GetHardcodedSummaries() {
|
|
return {};
|
|
}
|
|
|
|
HardcodedFormatters::HardcodedSyntheticFinder
|
|
Language::GetHardcodedSynthetics() {
|
|
return {};
|
|
}
|
|
|
|
std::vector<FormattersMatchCandidate>
|
|
Language::GetPossibleFormattersMatches(ValueObject &valobj,
|
|
lldb::DynamicValueType use_dynamic) {
|
|
return {};
|
|
}
|
|
|
|
struct language_name_pair {
|
|
const char *name;
|
|
LanguageType type;
|
|
};
|
|
|
|
struct language_name_pair language_names[] = {
|
|
// To allow GetNameForLanguageType to be a simple array lookup, the first
|
|
// part of this array must follow enum LanguageType exactly.
|
|
{"unknown", eLanguageTypeUnknown},
|
|
{"c89", eLanguageTypeC89},
|
|
{"c", eLanguageTypeC},
|
|
{"ada83", eLanguageTypeAda83},
|
|
{"c++", eLanguageTypeC_plus_plus},
|
|
{"cobol74", eLanguageTypeCobol74},
|
|
{"cobol85", eLanguageTypeCobol85},
|
|
{"fortran77", eLanguageTypeFortran77},
|
|
{"fortran90", eLanguageTypeFortran90},
|
|
{"pascal83", eLanguageTypePascal83},
|
|
{"modula2", eLanguageTypeModula2},
|
|
{"java", eLanguageTypeJava},
|
|
{"c99", eLanguageTypeC99},
|
|
{"ada95", eLanguageTypeAda95},
|
|
{"fortran95", eLanguageTypeFortran95},
|
|
{"pli", eLanguageTypePLI},
|
|
{"objective-c", eLanguageTypeObjC},
|
|
{"objective-c++", eLanguageTypeObjC_plus_plus},
|
|
{"upc", eLanguageTypeUPC},
|
|
{"d", eLanguageTypeD},
|
|
{"python", eLanguageTypePython},
|
|
{"opencl", eLanguageTypeOpenCL},
|
|
{"go", eLanguageTypeGo},
|
|
{"modula3", eLanguageTypeModula3},
|
|
{"haskell", eLanguageTypeHaskell},
|
|
{"c++03", eLanguageTypeC_plus_plus_03},
|
|
{"c++11", eLanguageTypeC_plus_plus_11},
|
|
{"ocaml", eLanguageTypeOCaml},
|
|
{"rust", eLanguageTypeRust},
|
|
{"c11", eLanguageTypeC11},
|
|
{"swift", eLanguageTypeSwift},
|
|
{"julia", eLanguageTypeJulia},
|
|
{"dylan", eLanguageTypeDylan},
|
|
{"c++14", eLanguageTypeC_plus_plus_14},
|
|
{"fortran03", eLanguageTypeFortran03},
|
|
{"fortran08", eLanguageTypeFortran08},
|
|
{"renderscript", eLanguageTypeRenderScript},
|
|
{"bliss", eLanguageTypeBLISS},
|
|
{"kotlin", eLanguageTypeKotlin},
|
|
{"zig", eLanguageTypeZig},
|
|
{"crystal", eLanguageTypeCrystal},
|
|
{"<invalid language>",
|
|
static_cast<LanguageType>(
|
|
0x0029)}, // Not yet taken by any language in the DWARF spec
|
|
// and thus has no entry in LanguageType
|
|
{"c++17", eLanguageTypeC_plus_plus_17},
|
|
{"c++20", eLanguageTypeC_plus_plus_20},
|
|
{"c17", eLanguageTypeC17},
|
|
{"fortran18", eLanguageTypeFortran18},
|
|
{"ada2005", eLanguageTypeAda2005},
|
|
{"ada2012", eLanguageTypeAda2012},
|
|
{"HIP", eLanguageTypeHIP},
|
|
{"assembly", eLanguageTypeAssembly},
|
|
{"c-sharp", eLanguageTypeC_sharp},
|
|
{"mojo", eLanguageTypeMojo},
|
|
// Vendor Extensions
|
|
{"assembler", eLanguageTypeMipsAssembler},
|
|
// Now synonyms, in arbitrary order
|
|
{"objc", eLanguageTypeObjC},
|
|
{"objc++", eLanguageTypeObjC_plus_plus},
|
|
{"pascal", eLanguageTypePascal83}};
|
|
|
|
static uint32_t num_languages =
|
|
sizeof(language_names) / sizeof(struct language_name_pair);
|
|
|
|
LanguageType Language::GetLanguageTypeFromString(llvm::StringRef string) {
|
|
for (const auto &L : language_names) {
|
|
if (string.equals_insensitive(L.name))
|
|
return L.type;
|
|
}
|
|
|
|
return eLanguageTypeUnknown;
|
|
}
|
|
|
|
const char *Language::GetNameForLanguageType(LanguageType language) {
|
|
if (language < num_languages)
|
|
return language_names[language].name;
|
|
else
|
|
return language_names[eLanguageTypeUnknown].name;
|
|
}
|
|
|
|
llvm::StringRef Language::GetDisplayNameForLanguageType(LanguageType language) {
|
|
return SourceLanguage(language).GetDescription();
|
|
}
|
|
|
|
void Language::PrintSupportedLanguagesForExpressions(Stream &s,
|
|
llvm::StringRef prefix,
|
|
llvm::StringRef suffix) {
|
|
auto supported = Language::GetLanguagesSupportingTypeSystemsForExpressions();
|
|
for (size_t idx = 0; idx < num_languages; ++idx) {
|
|
auto const &lang = language_names[idx];
|
|
if (supported[lang.type])
|
|
s << prefix << lang.name << suffix;
|
|
}
|
|
}
|
|
|
|
void Language::PrintAllLanguages(Stream &s, const char *prefix,
|
|
const char *suffix) {
|
|
for (uint32_t i = 1; i < num_languages; i++) {
|
|
s.Printf("%s%s%s", prefix, language_names[i].name, suffix);
|
|
}
|
|
}
|
|
|
|
void Language::ForAllLanguages(
|
|
llvm::function_ref<IterationAction(lldb::LanguageType)> callback) {
|
|
for (uint32_t i = 1; i < num_languages; i++) {
|
|
if (callback(language_names[i].type) == IterationAction::Stop)
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool Language::LanguageIsCPlusPlus(LanguageType language) {
|
|
switch (language) {
|
|
case eLanguageTypeC_plus_plus:
|
|
case eLanguageTypeC_plus_plus_03:
|
|
case eLanguageTypeC_plus_plus_11:
|
|
case eLanguageTypeC_plus_plus_14:
|
|
case eLanguageTypeC_plus_plus_17:
|
|
case eLanguageTypeC_plus_plus_20:
|
|
case eLanguageTypeObjC_plus_plus:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool Language::LanguageIsObjC(LanguageType language) {
|
|
switch (language) {
|
|
case eLanguageTypeObjC:
|
|
case eLanguageTypeObjC_plus_plus:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool Language::LanguageIsC(LanguageType language) {
|
|
switch (language) {
|
|
case eLanguageTypeC:
|
|
case eLanguageTypeC89:
|
|
case eLanguageTypeC99:
|
|
case eLanguageTypeC11:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool Language::LanguageIsCFamily(LanguageType language) {
|
|
switch (language) {
|
|
case eLanguageTypeC:
|
|
case eLanguageTypeC89:
|
|
case eLanguageTypeC99:
|
|
case eLanguageTypeC11:
|
|
case eLanguageTypeC_plus_plus:
|
|
case eLanguageTypeC_plus_plus_03:
|
|
case eLanguageTypeC_plus_plus_11:
|
|
case eLanguageTypeC_plus_plus_14:
|
|
case eLanguageTypeC_plus_plus_17:
|
|
case eLanguageTypeC_plus_plus_20:
|
|
case eLanguageTypeObjC_plus_plus:
|
|
case eLanguageTypeObjC:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool Language::LanguageIsPascal(LanguageType language) {
|
|
switch (language) {
|
|
case eLanguageTypePascal83:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
LanguageType Language::GetPrimaryLanguage(LanguageType language) {
|
|
switch (language) {
|
|
case eLanguageTypeC_plus_plus:
|
|
case eLanguageTypeC_plus_plus_03:
|
|
case eLanguageTypeC_plus_plus_11:
|
|
case eLanguageTypeC_plus_plus_14:
|
|
case eLanguageTypeC_plus_plus_17:
|
|
case eLanguageTypeC_plus_plus_20:
|
|
return eLanguageTypeC_plus_plus;
|
|
case eLanguageTypeC:
|
|
case eLanguageTypeC89:
|
|
case eLanguageTypeC99:
|
|
case eLanguageTypeC11:
|
|
return eLanguageTypeC;
|
|
case eLanguageTypeObjC:
|
|
case eLanguageTypeObjC_plus_plus:
|
|
return eLanguageTypeObjC;
|
|
case eLanguageTypePascal83:
|
|
case eLanguageTypeCobol74:
|
|
case eLanguageTypeCobol85:
|
|
case eLanguageTypeFortran77:
|
|
case eLanguageTypeFortran90:
|
|
case eLanguageTypeFortran95:
|
|
case eLanguageTypeFortran03:
|
|
case eLanguageTypeFortran08:
|
|
case eLanguageTypeAda83:
|
|
case eLanguageTypeAda95:
|
|
case eLanguageTypeModula2:
|
|
case eLanguageTypeJava:
|
|
case eLanguageTypePLI:
|
|
case eLanguageTypeUPC:
|
|
case eLanguageTypeD:
|
|
case eLanguageTypePython:
|
|
case eLanguageTypeOpenCL:
|
|
case eLanguageTypeGo:
|
|
case eLanguageTypeModula3:
|
|
case eLanguageTypeHaskell:
|
|
case eLanguageTypeOCaml:
|
|
case eLanguageTypeRust:
|
|
case eLanguageTypeSwift:
|
|
case eLanguageTypeJulia:
|
|
case eLanguageTypeDylan:
|
|
case eLanguageTypeMipsAssembler:
|
|
case eLanguageTypeMojo:
|
|
case eLanguageTypeUnknown:
|
|
default:
|
|
return language;
|
|
}
|
|
}
|
|
|
|
std::set<lldb::LanguageType> Language::GetSupportedLanguages() {
|
|
std::set<lldb::LanguageType> supported_languages;
|
|
ForEach([&](Language *lang) {
|
|
supported_languages.emplace(lang->GetLanguageType());
|
|
return IterationAction::Continue;
|
|
});
|
|
return supported_languages;
|
|
}
|
|
|
|
LanguageSet Language::GetLanguagesSupportingTypeSystems() {
|
|
return PluginManager::GetAllTypeSystemSupportedLanguagesForTypes();
|
|
}
|
|
|
|
LanguageSet Language::GetLanguagesSupportingTypeSystemsForExpressions() {
|
|
return PluginManager::GetAllTypeSystemSupportedLanguagesForExpressions();
|
|
}
|
|
|
|
LanguageSet Language::GetLanguagesSupportingREPLs() {
|
|
return PluginManager::GetREPLAllTypeSystemSupportedLanguages();
|
|
}
|
|
|
|
std::unique_ptr<Language::TypeScavenger> Language::GetTypeScavenger() {
|
|
return nullptr;
|
|
}
|
|
|
|
const char *Language::GetLanguageSpecificTypeLookupHelp() { return nullptr; }
|
|
|
|
size_t Language::TypeScavenger::Find(ExecutionContextScope *exe_scope,
|
|
const char *key, ResultSet &results,
|
|
bool append) {
|
|
if (!exe_scope || !exe_scope->CalculateTarget().get())
|
|
return false;
|
|
|
|
if (!key || !key[0])
|
|
return false;
|
|
|
|
if (!append)
|
|
results.clear();
|
|
|
|
size_t old_size = results.size();
|
|
|
|
if (this->Find_Impl(exe_scope, key, results))
|
|
return results.size() - old_size;
|
|
return 0;
|
|
}
|
|
|
|
bool Language::ImageListTypeScavenger::Find_Impl(
|
|
ExecutionContextScope *exe_scope, const char *key, ResultSet &results) {
|
|
bool result = false;
|
|
|
|
Target *target = exe_scope->CalculateTarget().get();
|
|
if (target) {
|
|
const auto &images(target->GetImages());
|
|
TypeQuery query(key);
|
|
TypeResults type_results;
|
|
images.FindTypes(nullptr, query, type_results);
|
|
for (const auto &match : type_results.GetTypeMap().Types()) {
|
|
if (match) {
|
|
CompilerType compiler_type(match->GetFullCompilerType());
|
|
compiler_type = AdjustForInclusion(compiler_type);
|
|
if (!compiler_type)
|
|
continue;
|
|
std::unique_ptr<Language::TypeScavenger::Result> scavengeresult(
|
|
new Result(compiler_type));
|
|
results.insert(std::move(scavengeresult));
|
|
result = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
std::pair<llvm::StringRef, llvm::StringRef>
|
|
Language::GetFormatterPrefixSuffix(llvm::StringRef type_hint) {
|
|
return std::pair<llvm::StringRef, llvm::StringRef>();
|
|
}
|
|
|
|
bool Language::DemangledNameContainsPath(llvm::StringRef path,
|
|
ConstString demangled) const {
|
|
// The base implementation does a simple contains comparision:
|
|
if (path.empty())
|
|
return false;
|
|
return demangled.GetStringRef().contains(path);
|
|
}
|
|
|
|
DumpValueObjectOptions::DeclPrintingHelper Language::GetDeclPrintingHelper() {
|
|
return nullptr;
|
|
}
|
|
|
|
LazyBool Language::IsLogicalTrue(ValueObject &valobj, Status &error) {
|
|
return eLazyBoolCalculate;
|
|
}
|
|
|
|
bool Language::IsNilReference(ValueObject &valobj) { return false; }
|
|
|
|
bool Language::IsUninitializedReference(ValueObject &valobj) { return false; }
|
|
|
|
bool Language::GetFunctionDisplayName(const SymbolContext &sc,
|
|
const ExecutionContext *exe_ctx,
|
|
FunctionNameRepresentation representation,
|
|
Stream &s) {
|
|
return false;
|
|
}
|
|
|
|
void Language::GetExceptionResolverDescription(bool catch_on, bool throw_on,
|
|
Stream &s) {
|
|
GetDefaultExceptionResolverDescription(catch_on, throw_on, s);
|
|
}
|
|
|
|
void Language::GetDefaultExceptionResolverDescription(bool catch_on,
|
|
bool throw_on,
|
|
Stream &s) {
|
|
s.Printf("Exception breakpoint (catch: %s throw: %s)",
|
|
catch_on ? "on" : "off", throw_on ? "on" : "off");
|
|
}
|
|
|
|
std::optional<bool> Language::GetBooleanFromString(llvm::StringRef str) const {
|
|
return llvm::StringSwitch<std::optional<bool>>(str)
|
|
.Case("true", {true})
|
|
.Case("false", {false})
|
|
.Default({});
|
|
}
|
|
|
|
// Constructor
|
|
Language::Language() = default;
|
|
|
|
// Destructor
|
|
Language::~Language() = default;
|
|
|
|
static std::optional<llvm::dwarf::SourceLanguage>
|
|
ToDwarfSourceLanguage(lldb::LanguageType language_type) {
|
|
if (language_type <= lldb::eLanguageTypeLastStandardLanguage)
|
|
return static_cast<llvm::dwarf::SourceLanguage>(language_type);
|
|
|
|
switch (language_type) {
|
|
case eLanguageTypeMipsAssembler:
|
|
return llvm::dwarf::DW_LANG_Mips_Assembler;
|
|
default:
|
|
return std::nullopt;
|
|
}
|
|
}
|
|
|
|
SourceLanguage::SourceLanguage(lldb::LanguageType language_type) {
|
|
std::optional<llvm::dwarf::SourceLanguage> dwarf_lang =
|
|
ToDwarfSourceLanguage(language_type);
|
|
if (!dwarf_lang)
|
|
return;
|
|
|
|
auto lname = llvm::dwarf::toDW_LNAME(*dwarf_lang);
|
|
if (!lname)
|
|
return;
|
|
name = lname->first;
|
|
version = lname->second;
|
|
}
|
|
|
|
lldb::LanguageType SourceLanguage::AsLanguageType() const {
|
|
if (auto lang = llvm::dwarf::toDW_LANG((llvm::dwarf::SourceLanguageName)name,
|
|
version))
|
|
return (lldb::LanguageType)*lang;
|
|
return lldb::eLanguageTypeUnknown;
|
|
}
|
|
|
|
llvm::StringRef SourceLanguage::GetDescription() const {
|
|
return llvm::dwarf::LanguageDescription(
|
|
static_cast<llvm::dwarf::SourceLanguageName>(name), version);
|
|
}
|
|
bool SourceLanguage::IsC() const { return name == llvm::dwarf::DW_LNAME_C; }
|
|
|
|
bool SourceLanguage::IsObjC() const {
|
|
return name == llvm::dwarf::DW_LNAME_ObjC;
|
|
}
|
|
|
|
bool SourceLanguage::IsCPlusPlus() const {
|
|
return name == llvm::dwarf::DW_LNAME_C_plus_plus;
|
|
}
|