2023-05-26 13:52:09 +01:00
|
|
|
/*
|
|
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
#include "Types.h"
|
|
|
|
|
|
|
|
#include "Visitor.h"
|
|
|
|
|
2023-07-26 15:31:53 +01:00
|
|
|
namespace oi::detail::type_graph {
|
2023-05-26 13:52:09 +01:00
|
|
|
|
2023-12-13 16:49:41 +00:00
|
|
|
#define X(OI_TYPE_NAME) \
|
|
|
|
void OI_TYPE_NAME::accept(Visitor<void>& v) { \
|
|
|
|
v.visit(*this); \
|
|
|
|
} \
|
|
|
|
drgn_type* OI_TYPE_NAME::accept(Visitor<drgn_type*>& v) { \
|
|
|
|
return v.visit(*this); \
|
|
|
|
} \
|
|
|
|
Type& OI_TYPE_NAME::accept(Visitor<Type&>& m) { \
|
|
|
|
return m.visit(*this); \
|
|
|
|
} \
|
|
|
|
void OI_TYPE_NAME::accept(ConstVisitor& v) const { \
|
|
|
|
v.visit(*this); \
|
2023-05-26 13:52:09 +01:00
|
|
|
}
|
|
|
|
OI_TYPE_LIST
|
|
|
|
#undef X
|
|
|
|
|
2023-07-26 10:38:02 +01:00
|
|
|
std::string Primitive::getName(Kind kind) {
|
|
|
|
switch (kind) {
|
2023-05-26 13:52:09 +01:00
|
|
|
case Kind::Int8:
|
|
|
|
return "int8_t";
|
|
|
|
case Kind::Int16:
|
|
|
|
return "int16_t";
|
|
|
|
case Kind::Int32:
|
|
|
|
return "int32_t";
|
|
|
|
case Kind::Int64:
|
|
|
|
return "int64_t";
|
|
|
|
case Kind::UInt8:
|
|
|
|
return "uint8_t";
|
|
|
|
case Kind::UInt16:
|
|
|
|
return "uint16_t";
|
|
|
|
case Kind::UInt32:
|
|
|
|
return "uint32_t";
|
|
|
|
case Kind::UInt64:
|
|
|
|
return "uint64_t";
|
|
|
|
case Kind::Float32:
|
|
|
|
return "float";
|
|
|
|
case Kind::Float64:
|
|
|
|
return "double";
|
|
|
|
case Kind::Float80:
|
|
|
|
abort();
|
|
|
|
case Kind::Float128:
|
|
|
|
return "long double";
|
|
|
|
case Kind::Bool:
|
|
|
|
return "bool";
|
2023-09-21 16:57:08 +01:00
|
|
|
case Kind::StubbedPointer:
|
|
|
|
return "StubbedPointer";
|
2023-05-26 13:52:09 +01:00
|
|
|
case Kind::Void:
|
|
|
|
return "void";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-21 16:57:08 +01:00
|
|
|
std::string_view Primitive::inputName() const {
|
|
|
|
static const std::string kStubbedPointer = "uintptr_t (stubbed)";
|
|
|
|
if (kind_ == Kind::StubbedPointer)
|
|
|
|
return kStubbedPointer;
|
|
|
|
return name_;
|
|
|
|
}
|
|
|
|
|
2023-05-26 13:52:09 +01:00
|
|
|
std::size_t Primitive::size() const {
|
|
|
|
switch (kind_) {
|
|
|
|
case Kind::Int8:
|
|
|
|
return 1;
|
|
|
|
case Kind::Int16:
|
|
|
|
return 2;
|
|
|
|
case Kind::Int32:
|
|
|
|
return 4;
|
|
|
|
case Kind::Int64:
|
|
|
|
return 8;
|
|
|
|
case Kind::UInt8:
|
|
|
|
return 1;
|
|
|
|
case Kind::UInt16:
|
|
|
|
return 2;
|
|
|
|
case Kind::UInt32:
|
|
|
|
return 4;
|
|
|
|
case Kind::UInt64:
|
|
|
|
return 8;
|
|
|
|
case Kind::Float32:
|
|
|
|
return 4;
|
|
|
|
case Kind::Float64:
|
|
|
|
return 8;
|
|
|
|
case Kind::Float80:
|
|
|
|
abort();
|
|
|
|
case Kind::Float128:
|
|
|
|
return 16;
|
|
|
|
case Kind::Bool:
|
|
|
|
return 1;
|
2023-09-21 16:57:08 +01:00
|
|
|
case Kind::StubbedPointer:
|
2023-05-26 13:52:09 +01:00
|
|
|
return sizeof(uintptr_t);
|
|
|
|
case Kind::Void:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Returns true if the provided class is "dynamic".
|
|
|
|
*
|
|
|
|
* From the Itanium C++ ABI, a dynamic class is defined as:
|
|
|
|
* A class requiring a virtual table pointer (because it or its bases have
|
|
|
|
* one or more virtual member functions or virtual base classes).
|
|
|
|
*/
|
|
|
|
bool Class::isDynamic() const {
|
|
|
|
if (virtuality() != 0 /*DW_VIRTUALITY_none*/) {
|
|
|
|
// Virtual class - not fully supported by OI yet
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const auto& func : functions) {
|
|
|
|
if (func.virtuality != 0 /*DW_VIRTUALITY_none*/) {
|
|
|
|
// Virtual function
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-07-07 16:17:03 +01:00
|
|
|
// TODO this function is a massive hack. don't do it like this please
|
|
|
|
Type& stripTypedefs(Type& type) {
|
|
|
|
Type* t = &type;
|
|
|
|
while (const Typedef* td = dynamic_cast<Typedef*>(t)) {
|
|
|
|
t = &td->underlyingType();
|
|
|
|
}
|
|
|
|
return *t;
|
|
|
|
}
|
|
|
|
|
2023-07-26 15:31:53 +01:00
|
|
|
} // namespace oi::detail::type_graph
|