summaryrefslogtreecommitdiff
path: root/objectivec/objc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'objectivec/objc.cpp')
-rw-r--r--objectivec/objc.cpp63
1 files changed, 38 insertions, 25 deletions
diff --git a/objectivec/objc.cpp b/objectivec/objc.cpp
index 9d35d5e9..4e36c9ed 100644
--- a/objectivec/objc.cpp
+++ b/objectivec/objc.cpp
@@ -1,6 +1,8 @@
#include "objc.h"
#include "inttypes.h"
#include <optional>
+#include <string>
+#include <type_traits>
#define RELEASE_ASSERT(condition) ((condition) ? (void)0 : (std::abort(), (void)0))
@@ -1098,37 +1100,51 @@ void ObjCProcessor::ReadIvarList(ObjCReader* reader, ClassBase& cls, std::string
}
}
+// Returns the type named `name`, creating it via `factory()` and
+// defining it on the view if it does not already exist.
+template <typename F>
+ requires (std::is_same_v<std::invoke_result_t<F>, Ref<Type>>)
+std::pair<QualifiedName, Ref<Type>> DefineNamedType(
+ Ref<BinaryView> view, const QualifiedName& name, F&& factory)
+{
+ auto typeID = Type::GenerateAutoTypeId("objc", name);
+ if (auto type = view->GetTypeById(typeID))
+ return {name, type};
+
+ auto type = factory();
+ auto definedName = view->DefineType(typeID, name, type);
+ return {definedName, type};
+}
std::pair<QualifiedName, Ref<Type>> finalizeStructureBuilder(
- Ref<BinaryView> m_data, StructureBuilder sb, std::string name)
+ Ref<BinaryView> m_data, StructureBuilder sb, const QualifiedName& name)
{
- auto classTypeStruct = sb.Finalize();
-
- QualifiedName classTypeName(name);
- auto classTypeId = Type::GenerateAutoTypeId("objc", classTypeName);
- auto classType = Type::StructureType(classTypeStruct);
- auto classQualName = m_data->DefineType(classTypeId, classTypeName, classType);
+ return DefineNamedType(m_data, name, [&]() {
+ auto classTypeStruct = sb.Finalize();
+ return Type::StructureType(classTypeStruct);
+ });
+}
- return {classQualName, classType};
+std::pair<QualifiedName, Ref<Type>> finalizeStructureBuilder(
+ Ref<BinaryView> m_data, StructureBuilder sb, const std::string& name)
+{
+ return finalizeStructureBuilder(m_data, std::move(sb), QualifiedName(name));
}
std::pair<QualifiedName, Ref<Type>> finalizeEnumerationBuilder(
- Ref<BinaryView> m_data, EnumerationBuilder eb, uint64_t size, QualifiedName name)
+ Ref<BinaryView> m_data, EnumerationBuilder eb, uint64_t size, const QualifiedName& name)
{
- auto enumTypeStruct = eb.Finalize();
-
- auto enumTypeId = Type::GenerateAutoTypeId("objc", name);
- auto enumType = Type::EnumerationType(enumTypeStruct, size);
- auto enumQualName = m_data->DefineType(enumTypeId, name, enumType);
-
- return {enumQualName, enumType};
+ return DefineNamedType(m_data, name, [&]() {
+ auto enumTypeStruct = eb.Finalize();
+ return Type::EnumerationType(enumTypeStruct, size);
+ });
}
-inline QualifiedName defineTypedef(Ref<BinaryView> m_data, const QualifiedName name, Ref<Type> type)
+inline QualifiedName defineTypedef(Ref<BinaryView> m_data, const QualifiedName& name, Ref<Type> type)
{
- auto typeID = Type::GenerateAutoTypeId("objc", name);
- m_data->DefineType(typeID, name, type);
- return m_data->GetTypeNameById(typeID);
+ return DefineNamedType(m_data, name, [&]() {
+ return type;
+ }).first;
}
void ObjCProcessor::GenerateClassTypes()
@@ -1528,11 +1544,8 @@ void ObjCProcessor::ProcessObjCData()
classBuilder.AddMember(Type::PointerType(addrSize, Type::VoidType()), "vtable");
classBuilder.AddMember(Type::PointerType(addrSize, Type::NamedType(m_data, m_typeNames.classRO)), "data");
- auto classTypeStruct = classBuilder.Finalize();
- auto classType = Type::StructureType(classTypeStruct);
- auto classQualName = m_data->DefineType(classTypeId, classTypeName, classType);
-
- m_typeNames.cls = classQualName;
+ type = finalizeStructureBuilder(m_data, classBuilder, classTypeName);
+ m_typeNames.cls = type.first;
StructureBuilder categoryBuilder;
categoryBuilder.AddMember(Type::PointerType(addrSize, Type::IntegerType(1, true)), "category_name");