blob: a74df4197a0a9fb29b1a4f653ad55c9fbbb098b8 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/developer/debug/zxdb/expr/builtin_types.h"
#include <lib/syslog/cpp/macros.h>
#include <map>
namespace zxdb {
namespace {
struct BuiltinTypeInfo {
const char* name;
uint32_t base_type;
uint32_t byte_size;
};
// TODO(brettw) this needs to handle compound types like "unsigned short" and "signed int". Note
// that the modifiers can appear in different orders like "signed short int" vs. "short signed int",
// and can also have interspersed CV-modifiers like "short volatile signed const int".
const BuiltinTypeInfo kCBuiltinInfo[] = {
// clang-format off
// This void type is a bit weird because the way that "void" is represented in DWARF is just by
// an absence of a type. But we can't really return that here. So we return it as a base type of
// "no base type".
{ "void", BaseType::kBaseTypeNone, 0 },
{ "bool", BaseType::kBaseTypeBoolean, 1 },
// Integer types.
{ "short", BaseType::kBaseTypeSigned, 2 }, // TODO: [un]signed
{ "int", BaseType::kBaseTypeSigned, 4 }, // TODO: [un]signed, long/short/"long long"
{ "unsigned", BaseType::kBaseTypeUnsigned, 4 },
{ "long", BaseType::kBaseTypeSigned, 8 }, // TODO: [un]signed, "long long"
// Floating-point types.
{ "float", BaseType::kBaseTypeFloat, 4 },
{ "double", BaseType::kBaseTypeFloat, 8 }, // TODO: "long double"
// Character types.
{ "char", BaseType::kBaseTypeSignedChar, 1 }, // TODO: [un]signed
{ "wchar_t", BaseType::kBaseTypeSigned, 4 }, // TODO: [un]signed
{ "char8_t", BaseType::kBaseTypeUTF, 1 },
{ "char16_t", BaseType::kBaseTypeUTF, 2 },
{ "char32_t", BaseType::kBaseTypeUTF, 4 },
// Main stdint types (not technically built-in, but commonly needed).
{ "int8_t", BaseType::kBaseTypeSignedChar, 1 },
{ "uint8_t", BaseType::kBaseTypeUnsignedChar, 1 },
{ "int16_t", BaseType::kBaseTypeSigned, 2 },
{ "uint16_t", BaseType::kBaseTypeUnsigned, 2 },
{ "int32_t", BaseType::kBaseTypeSigned, 4 },
{ "uint32_t", BaseType::kBaseTypeUnsigned, 4 },
{ "int64_t", BaseType::kBaseTypeSigned, 8 },
{ "uint64_t", BaseType::kBaseTypeUnsigned, 8 },
// Not technically defined in C but we need a name for 128-bit values.
{ "int128_t", BaseType::kBaseTypeSigned, 16 },
{ "uint128_t", BaseType::kBaseTypeUnsigned, 16 },
// Special Zircon types (see note below).
{ "zx_status_t", BaseType::kBaseTypeSigned, 4 },
// clang-format on
};
const BuiltinTypeInfo kRustBuiltinInfo[] = {
// clang-format off
{ "bool", BaseType::kBaseTypeBoolean, 1 },
{ "char", BaseType::kBaseTypeUnsignedChar, 4 },
// Integer types.
{ "i8", BaseType::kBaseTypeSigned, 1 },
{ "u8", BaseType::kBaseTypeUnsigned, 1 },
{ "i16", BaseType::kBaseTypeSigned, 2 },
{ "u16", BaseType::kBaseTypeUnsigned, 2 },
{ "i32", BaseType::kBaseTypeSigned, 4 },
{ "u32", BaseType::kBaseTypeUnsigned, 4 },
{ "i64", BaseType::kBaseTypeSigned, 8 },
{ "u64", BaseType::kBaseTypeUnsigned, 8 },
{ "i128", BaseType::kBaseTypeSigned, 16 },
{ "u128", BaseType::kBaseTypeUnsigned, 16 },
{ "isize", BaseType::kBaseTypeSigned, 8 }, // 64-bit system.
{ "usize", BaseType::kBaseTypeUnsigned, 8 },
// Floating-point types.
{ "f32", BaseType::kBaseTypeFloat, 4 },
{ "f64", BaseType::kBaseTypeFloat, 8 },
// clang-format on
};
// Note on zx_status_t: Normally this will be declared in the program as a typedef for an int32.
// Adding it here allows casting to it even if the typedef is not currently in scope, which in turn
// will trigger the special-cased pretty-printing to decode status values. This fallback doesn't
// define it as a typedef for simplicit, that could be added in the future if desired.
using BuiltinTypeInfoMap = std::map<std::string_view, const BuiltinTypeInfo*>;
const BuiltinTypeInfoMap* GetCBuiltinTypeMap() {
static BuiltinTypeInfoMap map;
if (map.empty()) {
for (const auto& cur : kCBuiltinInfo)
map[cur.name] = &cur;
}
return &map;
}
const BuiltinTypeInfoMap* GetRustBuiltinTypeMap() {
static BuiltinTypeInfoMap map;
if (map.empty()) {
for (const auto& cur : kRustBuiltinInfo)
map[cur.name] = &cur;
}
return &map;
}
} // namespace
fxl::RefPtr<BaseType> GetBuiltinType(ExprLanguage lang, std::string_view name) {
const BuiltinTypeInfoMap* map;
switch (lang) {
case ExprLanguage::kC:
map = GetCBuiltinTypeMap();
break;
case ExprLanguage::kRust:
map = GetRustBuiltinTypeMap();
break;
default:
FX_NOTREACHED();
return nullptr;
}
auto found = map->find(name);
if (found == map->end())
return nullptr;
const BuiltinTypeInfo& info = *found->second;
return fxl::MakeRefCounted<BaseType>(info.base_type, info.byte_size, info.name);
}
fxl::RefPtr<BaseType> GetBuiltinUnsigned64Type(ExprLanguage lang) {
switch (lang) {
case ExprLanguage::kC:
return fxl::MakeRefCounted<BaseType>(BaseType::kBaseTypeUnsigned, 8, "uint64_t");
case ExprLanguage::kRust:
return fxl::MakeRefCounted<BaseType>(BaseType::kBaseTypeUnsigned, 8, "u64");
}
FX_NOTREACHED();
return fxl::RefPtr<BaseType>();
}
fxl::RefPtr<BaseType> GetBuiltinUnsignedType(ExprLanguage lang, size_t byte_size) {
switch (lang) {
case ExprLanguage::kC:
switch (byte_size) {
case 1:
return GetBuiltinType(lang, "uint8_t");
case 2:
return GetBuiltinType(lang, "uint16_t");
case 4:
return GetBuiltinType(lang, "uint32_t");
case 8:
return GetBuiltinType(lang, "uint64_t");
case 16:
return GetBuiltinType(lang, "uint128_t");
}
break;
case ExprLanguage::kRust:
switch (byte_size) {
case 1:
return GetBuiltinType(lang, "u8");
case 2:
return GetBuiltinType(lang, "u16");
case 4:
return GetBuiltinType(lang, "u32");
case 8:
return GetBuiltinType(lang, "u64");
case 16:
return GetBuiltinType(lang, "u128");
}
break;
}
// No builtin, in this case just make up a type.
return fxl::MakeRefCounted<BaseType>(BaseType::kBaseTypeUnsigned, byte_size,
"nonstandard_unsigned");
}
fxl::RefPtr<BaseType> GetBuiltinFloatType(ExprLanguage lang, size_t byte_size) {
switch (lang) {
case ExprLanguage::kC:
switch (byte_size) {
case 4:
return GetBuiltinType(lang, "float");
case 8:
return GetBuiltinType(lang, "double");
case 10:
return GetBuiltinType(lang, "long double");
}
break;
case ExprLanguage::kRust:
switch (byte_size) {
case 4:
return GetBuiltinType(lang, "f32");
case 8:
return GetBuiltinType(lang, "f64");
}
break;
}
// No builtin, in this case just make up a type.
return fxl::MakeRefCounted<BaseType>(BaseType::kBaseTypeFloat, byte_size, "nonstandard_float");
}
} // namespace zxdb