1*9e3b08aeSAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2*9e3b08aeSAndroid Build Coastguard Worker // -*- mode: C++ -*-
3*9e3b08aeSAndroid Build Coastguard Worker //
4*9e3b08aeSAndroid Build Coastguard Worker // Copyright 2022-2024 Google LLC
5*9e3b08aeSAndroid Build Coastguard Worker //
6*9e3b08aeSAndroid Build Coastguard Worker // Licensed under the Apache License v2.0 with LLVM Exceptions (the
7*9e3b08aeSAndroid Build Coastguard Worker // "License"); you may not use this file except in compliance with the
8*9e3b08aeSAndroid Build Coastguard Worker // License. You may obtain a copy of the License at
9*9e3b08aeSAndroid Build Coastguard Worker //
10*9e3b08aeSAndroid Build Coastguard Worker // https://llvm.org/LICENSE.txt
11*9e3b08aeSAndroid Build Coastguard Worker //
12*9e3b08aeSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
13*9e3b08aeSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
14*9e3b08aeSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15*9e3b08aeSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
16*9e3b08aeSAndroid Build Coastguard Worker // limitations under the License.
17*9e3b08aeSAndroid Build Coastguard Worker //
18*9e3b08aeSAndroid Build Coastguard Worker // Author: Siddharth Nayyar
19*9e3b08aeSAndroid Build Coastguard Worker
20*9e3b08aeSAndroid Build Coastguard Worker #include "proto_writer.h"
21*9e3b08aeSAndroid Build Coastguard Worker
22*9e3b08aeSAndroid Build Coastguard Worker #include <algorithm>
23*9e3b08aeSAndroid Build Coastguard Worker #include <array>
24*9e3b08aeSAndroid Build Coastguard Worker #include <cstdint>
25*9e3b08aeSAndroid Build Coastguard Worker #include <iomanip>
26*9e3b08aeSAndroid Build Coastguard Worker #include <ios>
27*9e3b08aeSAndroid Build Coastguard Worker #include <ostream>
28*9e3b08aeSAndroid Build Coastguard Worker #include <sstream>
29*9e3b08aeSAndroid Build Coastguard Worker #include <tuple>
30*9e3b08aeSAndroid Build Coastguard Worker #include <unordered_map>
31*9e3b08aeSAndroid Build Coastguard Worker #include <unordered_set>
32*9e3b08aeSAndroid Build Coastguard Worker
33*9e3b08aeSAndroid Build Coastguard Worker #include <google/protobuf/descriptor.h>
34*9e3b08aeSAndroid Build Coastguard Worker #include <google/protobuf/io/zero_copy_stream.h>
35*9e3b08aeSAndroid Build Coastguard Worker #include <google/protobuf/repeated_ptr_field.h>
36*9e3b08aeSAndroid Build Coastguard Worker #include <google/protobuf/text_format.h>
37*9e3b08aeSAndroid Build Coastguard Worker #include "error.h"
38*9e3b08aeSAndroid Build Coastguard Worker #include "graph.h"
39*9e3b08aeSAndroid Build Coastguard Worker #include "naming.h"
40*9e3b08aeSAndroid Build Coastguard Worker #include "stable_hash.h"
41*9e3b08aeSAndroid Build Coastguard Worker #include "stg.pb.h"
42*9e3b08aeSAndroid Build Coastguard Worker
43*9e3b08aeSAndroid Build Coastguard Worker namespace stg {
44*9e3b08aeSAndroid Build Coastguard Worker namespace proto {
45*9e3b08aeSAndroid Build Coastguard Worker
46*9e3b08aeSAndroid Build Coastguard Worker namespace {
47*9e3b08aeSAndroid Build Coastguard Worker
48*9e3b08aeSAndroid Build Coastguard Worker class StableId {
49*9e3b08aeSAndroid Build Coastguard Worker public:
StableId(const Graph & graph)50*9e3b08aeSAndroid Build Coastguard Worker explicit StableId(const Graph& graph) : stable_hash_(graph) {}
51*9e3b08aeSAndroid Build Coastguard Worker
operator ()(Id id)52*9e3b08aeSAndroid Build Coastguard Worker uint32_t operator()(Id id) {
53*9e3b08aeSAndroid Build Coastguard Worker return stable_hash_(id).value;
54*9e3b08aeSAndroid Build Coastguard Worker }
55*9e3b08aeSAndroid Build Coastguard Worker
56*9e3b08aeSAndroid Build Coastguard Worker private:
57*9e3b08aeSAndroid Build Coastguard Worker StableHash stable_hash_;
58*9e3b08aeSAndroid Build Coastguard Worker };
59*9e3b08aeSAndroid Build Coastguard Worker
60*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
61*9e3b08aeSAndroid Build Coastguard Worker struct Transform {
Transformstg::proto::__anon9c9f2c680111::Transform62*9e3b08aeSAndroid Build Coastguard Worker Transform(const Graph& graph, proto::STG& stg, MapId& map_id)
63*9e3b08aeSAndroid Build Coastguard Worker : graph(graph), stg(stg), map_id(map_id) {}
64*9e3b08aeSAndroid Build Coastguard Worker
65*9e3b08aeSAndroid Build Coastguard Worker uint32_t operator()(Id);
66*9e3b08aeSAndroid Build Coastguard Worker
67*9e3b08aeSAndroid Build Coastguard Worker void operator()(const stg::Special&, uint32_t);
68*9e3b08aeSAndroid Build Coastguard Worker void operator()(const stg::PointerReference&, uint32_t);
69*9e3b08aeSAndroid Build Coastguard Worker void operator()(const stg::PointerToMember&, uint32_t);
70*9e3b08aeSAndroid Build Coastguard Worker void operator()(const stg::Typedef&, uint32_t);
71*9e3b08aeSAndroid Build Coastguard Worker void operator()(const stg::Qualified&, uint32_t);
72*9e3b08aeSAndroid Build Coastguard Worker void operator()(const stg::Primitive&, uint32_t);
73*9e3b08aeSAndroid Build Coastguard Worker void operator()(const stg::Array&, uint32_t);
74*9e3b08aeSAndroid Build Coastguard Worker void operator()(const stg::BaseClass&, uint32_t);
75*9e3b08aeSAndroid Build Coastguard Worker void operator()(const stg::Method&, uint32_t);
76*9e3b08aeSAndroid Build Coastguard Worker void operator()(const stg::Member&, uint32_t);
77*9e3b08aeSAndroid Build Coastguard Worker void operator()(const stg::VariantMember&, uint32_t);
78*9e3b08aeSAndroid Build Coastguard Worker void operator()(const stg::StructUnion&, uint32_t);
79*9e3b08aeSAndroid Build Coastguard Worker void operator()(const stg::Enumeration&, uint32_t);
80*9e3b08aeSAndroid Build Coastguard Worker void operator()(const stg::Variant&, uint32_t);
81*9e3b08aeSAndroid Build Coastguard Worker void operator()(const stg::Function&, uint32_t);
82*9e3b08aeSAndroid Build Coastguard Worker void operator()(const stg::ElfSymbol&, uint32_t);
83*9e3b08aeSAndroid Build Coastguard Worker void operator()(const stg::Interface&, uint32_t);
84*9e3b08aeSAndroid Build Coastguard Worker
85*9e3b08aeSAndroid Build Coastguard Worker Special::Kind operator()(stg::Special::Kind);
86*9e3b08aeSAndroid Build Coastguard Worker PointerReference::Kind operator()(stg::PointerReference::Kind);
87*9e3b08aeSAndroid Build Coastguard Worker Qualified::Qualifier operator()(stg::Qualifier);
88*9e3b08aeSAndroid Build Coastguard Worker Primitive::Encoding operator()(stg::Primitive::Encoding);
89*9e3b08aeSAndroid Build Coastguard Worker BaseClass::Inheritance operator()(stg::BaseClass::Inheritance);
90*9e3b08aeSAndroid Build Coastguard Worker StructUnion::Kind operator()(stg::StructUnion::Kind);
91*9e3b08aeSAndroid Build Coastguard Worker ElfSymbol::SymbolType operator()(stg::ElfSymbol::SymbolType);
92*9e3b08aeSAndroid Build Coastguard Worker ElfSymbol::Binding operator()(stg::ElfSymbol::Binding);
93*9e3b08aeSAndroid Build Coastguard Worker ElfSymbol::Visibility operator()(stg::ElfSymbol::Visibility);
94*9e3b08aeSAndroid Build Coastguard Worker
GetInternalIdByExternalIdMapstg::proto::__anon9c9f2c680111::Transform95*9e3b08aeSAndroid Build Coastguard Worker std::unordered_map<uint32_t, Id> GetInternalIdByExternalIdMap() {
96*9e3b08aeSAndroid Build Coastguard Worker std::unordered_map<uint32_t, Id> internal_id_map;
97*9e3b08aeSAndroid Build Coastguard Worker for (const auto& [id, ext_id] : external_id_by_internal_id) {
98*9e3b08aeSAndroid Build Coastguard Worker internal_id_map.emplace(ext_id, id);
99*9e3b08aeSAndroid Build Coastguard Worker }
100*9e3b08aeSAndroid Build Coastguard Worker return internal_id_map;
101*9e3b08aeSAndroid Build Coastguard Worker }
102*9e3b08aeSAndroid Build Coastguard Worker
103*9e3b08aeSAndroid Build Coastguard Worker const Graph& graph;
104*9e3b08aeSAndroid Build Coastguard Worker proto::STG& stg;
105*9e3b08aeSAndroid Build Coastguard Worker std::unordered_map<Id, uint32_t> external_id_by_internal_id;
106*9e3b08aeSAndroid Build Coastguard Worker std::unordered_set<uint32_t> used_ids;
107*9e3b08aeSAndroid Build Coastguard Worker
108*9e3b08aeSAndroid Build Coastguard Worker // Function object: Id -> uint32_t
109*9e3b08aeSAndroid Build Coastguard Worker MapId& map_id;
110*9e3b08aeSAndroid Build Coastguard Worker };
111*9e3b08aeSAndroid Build Coastguard Worker
112*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(Id id)113*9e3b08aeSAndroid Build Coastguard Worker uint32_t Transform<MapId>::operator()(Id id) {
114*9e3b08aeSAndroid Build Coastguard Worker auto [it, inserted] = external_id_by_internal_id.emplace(id, 0);
115*9e3b08aeSAndroid Build Coastguard Worker if (inserted) {
116*9e3b08aeSAndroid Build Coastguard Worker uint32_t mapped_id = map_id(id);
117*9e3b08aeSAndroid Build Coastguard Worker
118*9e3b08aeSAndroid Build Coastguard Worker // Ensure uniqueness of external ids. It is best to probe here since id
119*9e3b08aeSAndroid Build Coastguard Worker // generators will not in general guarantee that the mapping from internal
120*9e3b08aeSAndroid Build Coastguard Worker // ids to external ids will be injective.
121*9e3b08aeSAndroid Build Coastguard Worker while (!used_ids.insert(mapped_id).second) {
122*9e3b08aeSAndroid Build Coastguard Worker ++mapped_id;
123*9e3b08aeSAndroid Build Coastguard Worker }
124*9e3b08aeSAndroid Build Coastguard Worker it->second = mapped_id;
125*9e3b08aeSAndroid Build Coastguard Worker graph.Apply(*this, id, mapped_id);
126*9e3b08aeSAndroid Build Coastguard Worker }
127*9e3b08aeSAndroid Build Coastguard Worker return it->second;
128*9e3b08aeSAndroid Build Coastguard Worker }
129*9e3b08aeSAndroid Build Coastguard Worker
130*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(const stg::Special & x,uint32_t id)131*9e3b08aeSAndroid Build Coastguard Worker void Transform<MapId>::operator()(const stg::Special& x, uint32_t id) {
132*9e3b08aeSAndroid Build Coastguard Worker auto& special = *stg.add_special();
133*9e3b08aeSAndroid Build Coastguard Worker special.set_id(id);
134*9e3b08aeSAndroid Build Coastguard Worker special.set_kind((*this)(x.kind));
135*9e3b08aeSAndroid Build Coastguard Worker }
136*9e3b08aeSAndroid Build Coastguard Worker
137*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(const stg::PointerReference & x,uint32_t id)138*9e3b08aeSAndroid Build Coastguard Worker void Transform<MapId>::operator()(const stg::PointerReference& x, uint32_t id) {
139*9e3b08aeSAndroid Build Coastguard Worker auto& pointer_reference = *stg.add_pointer_reference();
140*9e3b08aeSAndroid Build Coastguard Worker pointer_reference.set_id(id);
141*9e3b08aeSAndroid Build Coastguard Worker pointer_reference.set_kind((*this)(x.kind));
142*9e3b08aeSAndroid Build Coastguard Worker pointer_reference.set_pointee_type_id((*this)(x.pointee_type_id));
143*9e3b08aeSAndroid Build Coastguard Worker }
144*9e3b08aeSAndroid Build Coastguard Worker
145*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(const stg::PointerToMember & x,uint32_t id)146*9e3b08aeSAndroid Build Coastguard Worker void Transform<MapId>::operator()(const stg::PointerToMember& x, uint32_t id) {
147*9e3b08aeSAndroid Build Coastguard Worker auto& pointer_to_member = *stg.add_pointer_to_member();
148*9e3b08aeSAndroid Build Coastguard Worker pointer_to_member.set_id(id);
149*9e3b08aeSAndroid Build Coastguard Worker pointer_to_member.set_containing_type_id((*this)(x.containing_type_id));
150*9e3b08aeSAndroid Build Coastguard Worker pointer_to_member.set_pointee_type_id((*this)(x.pointee_type_id));
151*9e3b08aeSAndroid Build Coastguard Worker }
152*9e3b08aeSAndroid Build Coastguard Worker
153*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(const stg::Typedef & x,uint32_t id)154*9e3b08aeSAndroid Build Coastguard Worker void Transform<MapId>::operator()(const stg::Typedef& x, uint32_t id) {
155*9e3b08aeSAndroid Build Coastguard Worker auto& typedef_ = *stg.add_typedef_();
156*9e3b08aeSAndroid Build Coastguard Worker typedef_.set_id(id);
157*9e3b08aeSAndroid Build Coastguard Worker typedef_.set_name(x.name);
158*9e3b08aeSAndroid Build Coastguard Worker typedef_.set_referred_type_id((*this)(x.referred_type_id));
159*9e3b08aeSAndroid Build Coastguard Worker }
160*9e3b08aeSAndroid Build Coastguard Worker
161*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(const stg::Qualified & x,uint32_t id)162*9e3b08aeSAndroid Build Coastguard Worker void Transform<MapId>::operator()(const stg::Qualified& x, uint32_t id) {
163*9e3b08aeSAndroid Build Coastguard Worker auto& qualified = *stg.add_qualified();
164*9e3b08aeSAndroid Build Coastguard Worker qualified.set_id(id);
165*9e3b08aeSAndroid Build Coastguard Worker qualified.set_qualifier((*this)(x.qualifier));
166*9e3b08aeSAndroid Build Coastguard Worker qualified.set_qualified_type_id((*this)(x.qualified_type_id));
167*9e3b08aeSAndroid Build Coastguard Worker }
168*9e3b08aeSAndroid Build Coastguard Worker
169*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(const stg::Primitive & x,uint32_t id)170*9e3b08aeSAndroid Build Coastguard Worker void Transform<MapId>::operator()(const stg::Primitive& x, uint32_t id) {
171*9e3b08aeSAndroid Build Coastguard Worker auto& primitive = *stg.add_primitive();
172*9e3b08aeSAndroid Build Coastguard Worker primitive.set_id(id);
173*9e3b08aeSAndroid Build Coastguard Worker primitive.set_name(x.name);
174*9e3b08aeSAndroid Build Coastguard Worker if (x.encoding) {
175*9e3b08aeSAndroid Build Coastguard Worker primitive.set_encoding((*this)(*x.encoding));
176*9e3b08aeSAndroid Build Coastguard Worker }
177*9e3b08aeSAndroid Build Coastguard Worker primitive.set_bytesize(x.bytesize);
178*9e3b08aeSAndroid Build Coastguard Worker }
179*9e3b08aeSAndroid Build Coastguard Worker
180*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(const stg::Array & x,uint32_t id)181*9e3b08aeSAndroid Build Coastguard Worker void Transform<MapId>::operator()(const stg::Array& x, uint32_t id) {
182*9e3b08aeSAndroid Build Coastguard Worker auto& array = *stg.add_array();
183*9e3b08aeSAndroid Build Coastguard Worker array.set_id(id);
184*9e3b08aeSAndroid Build Coastguard Worker array.set_number_of_elements(x.number_of_elements);
185*9e3b08aeSAndroid Build Coastguard Worker array.set_element_type_id((*this)(x.element_type_id));
186*9e3b08aeSAndroid Build Coastguard Worker }
187*9e3b08aeSAndroid Build Coastguard Worker
188*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(const stg::BaseClass & x,uint32_t id)189*9e3b08aeSAndroid Build Coastguard Worker void Transform<MapId>::operator()(const stg::BaseClass& x, uint32_t id) {
190*9e3b08aeSAndroid Build Coastguard Worker auto& base_class = *stg.add_base_class();
191*9e3b08aeSAndroid Build Coastguard Worker base_class.set_id(id);
192*9e3b08aeSAndroid Build Coastguard Worker base_class.set_type_id((*this)(x.type_id));
193*9e3b08aeSAndroid Build Coastguard Worker base_class.set_offset(x.offset);
194*9e3b08aeSAndroid Build Coastguard Worker base_class.set_inheritance((*this)(x.inheritance));
195*9e3b08aeSAndroid Build Coastguard Worker }
196*9e3b08aeSAndroid Build Coastguard Worker
197*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(const stg::Method & x,uint32_t id)198*9e3b08aeSAndroid Build Coastguard Worker void Transform<MapId>::operator()(const stg::Method& x, uint32_t id) {
199*9e3b08aeSAndroid Build Coastguard Worker auto& method = *stg.add_method();
200*9e3b08aeSAndroid Build Coastguard Worker method.set_id(id);
201*9e3b08aeSAndroid Build Coastguard Worker method.set_mangled_name(x.mangled_name);
202*9e3b08aeSAndroid Build Coastguard Worker method.set_name(x.name);
203*9e3b08aeSAndroid Build Coastguard Worker method.set_vtable_offset(x.vtable_offset);
204*9e3b08aeSAndroid Build Coastguard Worker method.set_type_id((*this)(x.type_id));
205*9e3b08aeSAndroid Build Coastguard Worker }
206*9e3b08aeSAndroid Build Coastguard Worker
207*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(const stg::Member & x,uint32_t id)208*9e3b08aeSAndroid Build Coastguard Worker void Transform<MapId>::operator()(const stg::Member& x, uint32_t id) {
209*9e3b08aeSAndroid Build Coastguard Worker auto& member = *stg.add_member();
210*9e3b08aeSAndroid Build Coastguard Worker member.set_id(id);
211*9e3b08aeSAndroid Build Coastguard Worker member.set_name(x.name);
212*9e3b08aeSAndroid Build Coastguard Worker member.set_type_id((*this)(x.type_id));
213*9e3b08aeSAndroid Build Coastguard Worker member.set_offset(x.offset);
214*9e3b08aeSAndroid Build Coastguard Worker member.set_bitsize(x.bitsize);
215*9e3b08aeSAndroid Build Coastguard Worker }
216*9e3b08aeSAndroid Build Coastguard Worker
217*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(const stg::VariantMember & x,uint32_t id)218*9e3b08aeSAndroid Build Coastguard Worker void Transform<MapId>::operator()(const stg::VariantMember& x, uint32_t id) {
219*9e3b08aeSAndroid Build Coastguard Worker auto& variant_member = *stg.add_variant_member();
220*9e3b08aeSAndroid Build Coastguard Worker variant_member.set_id(id);
221*9e3b08aeSAndroid Build Coastguard Worker variant_member.set_name(x.name);
222*9e3b08aeSAndroid Build Coastguard Worker if (x.discriminant_value) {
223*9e3b08aeSAndroid Build Coastguard Worker variant_member.set_discriminant_value(*x.discriminant_value);
224*9e3b08aeSAndroid Build Coastguard Worker }
225*9e3b08aeSAndroid Build Coastguard Worker variant_member.set_type_id((*this)(x.type_id));
226*9e3b08aeSAndroid Build Coastguard Worker }
227*9e3b08aeSAndroid Build Coastguard Worker
228*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(const stg::StructUnion & x,uint32_t id)229*9e3b08aeSAndroid Build Coastguard Worker void Transform<MapId>::operator()(const stg::StructUnion& x, uint32_t id) {
230*9e3b08aeSAndroid Build Coastguard Worker auto& struct_union = *stg.add_struct_union();
231*9e3b08aeSAndroid Build Coastguard Worker struct_union.set_id(id);
232*9e3b08aeSAndroid Build Coastguard Worker struct_union.set_kind((*this)(x.kind));
233*9e3b08aeSAndroid Build Coastguard Worker struct_union.set_name(x.name);
234*9e3b08aeSAndroid Build Coastguard Worker if (x.definition) {
235*9e3b08aeSAndroid Build Coastguard Worker auto& definition = *struct_union.mutable_definition();
236*9e3b08aeSAndroid Build Coastguard Worker definition.set_bytesize(x.definition->bytesize);
237*9e3b08aeSAndroid Build Coastguard Worker for (const auto id : x.definition->base_classes) {
238*9e3b08aeSAndroid Build Coastguard Worker definition.add_base_class_id((*this)(id));
239*9e3b08aeSAndroid Build Coastguard Worker }
240*9e3b08aeSAndroid Build Coastguard Worker for (const auto id : x.definition->methods) {
241*9e3b08aeSAndroid Build Coastguard Worker definition.add_method_id((*this)(id));
242*9e3b08aeSAndroid Build Coastguard Worker }
243*9e3b08aeSAndroid Build Coastguard Worker for (const auto id : x.definition->members) {
244*9e3b08aeSAndroid Build Coastguard Worker definition.add_member_id((*this)(id));
245*9e3b08aeSAndroid Build Coastguard Worker }
246*9e3b08aeSAndroid Build Coastguard Worker }
247*9e3b08aeSAndroid Build Coastguard Worker }
248*9e3b08aeSAndroid Build Coastguard Worker
249*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(const stg::Enumeration & x,uint32_t id)250*9e3b08aeSAndroid Build Coastguard Worker void Transform<MapId>::operator()(const stg::Enumeration& x, uint32_t id) {
251*9e3b08aeSAndroid Build Coastguard Worker auto& enumeration = *stg.add_enumeration();
252*9e3b08aeSAndroid Build Coastguard Worker enumeration.set_id(id);
253*9e3b08aeSAndroid Build Coastguard Worker enumeration.set_name(x.name);
254*9e3b08aeSAndroid Build Coastguard Worker if (x.definition) {
255*9e3b08aeSAndroid Build Coastguard Worker auto& definition = *enumeration.mutable_definition();
256*9e3b08aeSAndroid Build Coastguard Worker definition.set_underlying_type_id(
257*9e3b08aeSAndroid Build Coastguard Worker (*this)(x.definition->underlying_type_id));
258*9e3b08aeSAndroid Build Coastguard Worker for (const auto& [name, value] : x.definition->enumerators) {
259*9e3b08aeSAndroid Build Coastguard Worker auto& enumerator = *definition.add_enumerator();
260*9e3b08aeSAndroid Build Coastguard Worker enumerator.set_name(name);
261*9e3b08aeSAndroid Build Coastguard Worker enumerator.set_value(value);
262*9e3b08aeSAndroid Build Coastguard Worker }
263*9e3b08aeSAndroid Build Coastguard Worker }
264*9e3b08aeSAndroid Build Coastguard Worker }
265*9e3b08aeSAndroid Build Coastguard Worker
266*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(const stg::Variant & x,uint32_t id)267*9e3b08aeSAndroid Build Coastguard Worker void Transform<MapId>::operator()(const stg::Variant& x, uint32_t id) {
268*9e3b08aeSAndroid Build Coastguard Worker auto& variant = *stg.add_variant();
269*9e3b08aeSAndroid Build Coastguard Worker variant.set_id(id);
270*9e3b08aeSAndroid Build Coastguard Worker variant.set_name(x.name);
271*9e3b08aeSAndroid Build Coastguard Worker variant.set_bytesize(x.bytesize);
272*9e3b08aeSAndroid Build Coastguard Worker if (x.discriminant.has_value()) {
273*9e3b08aeSAndroid Build Coastguard Worker variant.set_discriminant((*this)(x.discriminant.value()));
274*9e3b08aeSAndroid Build Coastguard Worker }
275*9e3b08aeSAndroid Build Coastguard Worker for (const auto id : x.members) {
276*9e3b08aeSAndroid Build Coastguard Worker variant.add_member_id((*this)(id));
277*9e3b08aeSAndroid Build Coastguard Worker }
278*9e3b08aeSAndroid Build Coastguard Worker }
279*9e3b08aeSAndroid Build Coastguard Worker
280*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(const stg::Function & x,uint32_t id)281*9e3b08aeSAndroid Build Coastguard Worker void Transform<MapId>::operator()(const stg::Function& x, uint32_t id) {
282*9e3b08aeSAndroid Build Coastguard Worker auto& function = *stg.add_function();
283*9e3b08aeSAndroid Build Coastguard Worker function.set_id(id);
284*9e3b08aeSAndroid Build Coastguard Worker function.set_return_type_id((*this)(x.return_type_id));
285*9e3b08aeSAndroid Build Coastguard Worker for (const auto id : x.parameters) {
286*9e3b08aeSAndroid Build Coastguard Worker function.add_parameter_id((*this)(id));
287*9e3b08aeSAndroid Build Coastguard Worker }
288*9e3b08aeSAndroid Build Coastguard Worker }
289*9e3b08aeSAndroid Build Coastguard Worker
290*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(const stg::ElfSymbol & x,uint32_t id)291*9e3b08aeSAndroid Build Coastguard Worker void Transform<MapId>::operator()(const stg::ElfSymbol& x, uint32_t id) {
292*9e3b08aeSAndroid Build Coastguard Worker auto& elf_symbol = *stg.add_elf_symbol();
293*9e3b08aeSAndroid Build Coastguard Worker elf_symbol.set_id(id);
294*9e3b08aeSAndroid Build Coastguard Worker elf_symbol.set_name(x.symbol_name);
295*9e3b08aeSAndroid Build Coastguard Worker if (x.version_info) {
296*9e3b08aeSAndroid Build Coastguard Worker auto& version_info = *elf_symbol.mutable_version_info();
297*9e3b08aeSAndroid Build Coastguard Worker version_info.set_is_default(x.version_info->is_default);
298*9e3b08aeSAndroid Build Coastguard Worker version_info.set_name(x.version_info->name);
299*9e3b08aeSAndroid Build Coastguard Worker }
300*9e3b08aeSAndroid Build Coastguard Worker elf_symbol.set_is_defined(x.is_defined);
301*9e3b08aeSAndroid Build Coastguard Worker elf_symbol.set_symbol_type((*this)(x.symbol_type));
302*9e3b08aeSAndroid Build Coastguard Worker elf_symbol.set_binding((*this)(x.binding));
303*9e3b08aeSAndroid Build Coastguard Worker elf_symbol.set_visibility((*this)(x.visibility));
304*9e3b08aeSAndroid Build Coastguard Worker if (x.crc) {
305*9e3b08aeSAndroid Build Coastguard Worker elf_symbol.set_crc(x.crc->number);
306*9e3b08aeSAndroid Build Coastguard Worker }
307*9e3b08aeSAndroid Build Coastguard Worker if (x.ns) {
308*9e3b08aeSAndroid Build Coastguard Worker elf_symbol.set_namespace_(*x.ns);
309*9e3b08aeSAndroid Build Coastguard Worker }
310*9e3b08aeSAndroid Build Coastguard Worker if (x.type_id) {
311*9e3b08aeSAndroid Build Coastguard Worker elf_symbol.set_type_id((*this)(*x.type_id));
312*9e3b08aeSAndroid Build Coastguard Worker }
313*9e3b08aeSAndroid Build Coastguard Worker if (x.full_name) {
314*9e3b08aeSAndroid Build Coastguard Worker elf_symbol.set_full_name(*x.full_name);
315*9e3b08aeSAndroid Build Coastguard Worker }
316*9e3b08aeSAndroid Build Coastguard Worker }
317*9e3b08aeSAndroid Build Coastguard Worker
318*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(const stg::Interface & x,uint32_t id)319*9e3b08aeSAndroid Build Coastguard Worker void Transform<MapId>::operator()(const stg::Interface& x, uint32_t id) {
320*9e3b08aeSAndroid Build Coastguard Worker auto& interface = *stg.add_interface();
321*9e3b08aeSAndroid Build Coastguard Worker interface.set_id(id);
322*9e3b08aeSAndroid Build Coastguard Worker for (const auto& [_, id] : x.symbols) {
323*9e3b08aeSAndroid Build Coastguard Worker interface.add_symbol_id((*this)(id));
324*9e3b08aeSAndroid Build Coastguard Worker }
325*9e3b08aeSAndroid Build Coastguard Worker for (const auto& [_, id] : x.types) {
326*9e3b08aeSAndroid Build Coastguard Worker interface.add_type_id((*this)(id));
327*9e3b08aeSAndroid Build Coastguard Worker }
328*9e3b08aeSAndroid Build Coastguard Worker }
329*9e3b08aeSAndroid Build Coastguard Worker
330*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(stg::PointerReference::Kind x)331*9e3b08aeSAndroid Build Coastguard Worker PointerReference::Kind Transform<MapId>::operator()(
332*9e3b08aeSAndroid Build Coastguard Worker stg::PointerReference::Kind x) {
333*9e3b08aeSAndroid Build Coastguard Worker switch (x) {
334*9e3b08aeSAndroid Build Coastguard Worker case stg::PointerReference::Kind::POINTER:
335*9e3b08aeSAndroid Build Coastguard Worker return PointerReference::POINTER;
336*9e3b08aeSAndroid Build Coastguard Worker case stg::PointerReference::Kind::LVALUE_REFERENCE:
337*9e3b08aeSAndroid Build Coastguard Worker return PointerReference::LVALUE_REFERENCE;
338*9e3b08aeSAndroid Build Coastguard Worker case stg::PointerReference::Kind::RVALUE_REFERENCE:
339*9e3b08aeSAndroid Build Coastguard Worker return PointerReference::RVALUE_REFERENCE;
340*9e3b08aeSAndroid Build Coastguard Worker }
341*9e3b08aeSAndroid Build Coastguard Worker }
342*9e3b08aeSAndroid Build Coastguard Worker
343*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(stg::Special::Kind x)344*9e3b08aeSAndroid Build Coastguard Worker Special::Kind Transform<MapId>::operator()(
345*9e3b08aeSAndroid Build Coastguard Worker stg::Special::Kind x) {
346*9e3b08aeSAndroid Build Coastguard Worker switch (x) {
347*9e3b08aeSAndroid Build Coastguard Worker case stg::Special::Kind::VOID:
348*9e3b08aeSAndroid Build Coastguard Worker return Special::VOID;
349*9e3b08aeSAndroid Build Coastguard Worker case stg::Special::Kind::VARIADIC:
350*9e3b08aeSAndroid Build Coastguard Worker return Special::VARIADIC;
351*9e3b08aeSAndroid Build Coastguard Worker case stg::Special::Kind::NULLPTR:
352*9e3b08aeSAndroid Build Coastguard Worker return Special::NULLPTR;
353*9e3b08aeSAndroid Build Coastguard Worker }
354*9e3b08aeSAndroid Build Coastguard Worker }
355*9e3b08aeSAndroid Build Coastguard Worker
356*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(stg::Qualifier x)357*9e3b08aeSAndroid Build Coastguard Worker Qualified::Qualifier Transform<MapId>::operator()(stg::Qualifier x) {
358*9e3b08aeSAndroid Build Coastguard Worker switch (x) {
359*9e3b08aeSAndroid Build Coastguard Worker case stg::Qualifier::CONST:
360*9e3b08aeSAndroid Build Coastguard Worker return Qualified::CONST;
361*9e3b08aeSAndroid Build Coastguard Worker case stg::Qualifier::VOLATILE:
362*9e3b08aeSAndroid Build Coastguard Worker return Qualified::VOLATILE;
363*9e3b08aeSAndroid Build Coastguard Worker case stg::Qualifier::RESTRICT:
364*9e3b08aeSAndroid Build Coastguard Worker return Qualified::RESTRICT;
365*9e3b08aeSAndroid Build Coastguard Worker case stg::Qualifier::ATOMIC:
366*9e3b08aeSAndroid Build Coastguard Worker return Qualified::ATOMIC;
367*9e3b08aeSAndroid Build Coastguard Worker }
368*9e3b08aeSAndroid Build Coastguard Worker }
369*9e3b08aeSAndroid Build Coastguard Worker
370*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(stg::Primitive::Encoding x)371*9e3b08aeSAndroid Build Coastguard Worker Primitive::Encoding Transform<MapId>::operator()(stg::Primitive::Encoding x) {
372*9e3b08aeSAndroid Build Coastguard Worker switch (x) {
373*9e3b08aeSAndroid Build Coastguard Worker case stg::Primitive::Encoding::BOOLEAN:
374*9e3b08aeSAndroid Build Coastguard Worker return Primitive::BOOLEAN;
375*9e3b08aeSAndroid Build Coastguard Worker case stg::Primitive::Encoding::SIGNED_INTEGER:
376*9e3b08aeSAndroid Build Coastguard Worker return Primitive::SIGNED_INTEGER;
377*9e3b08aeSAndroid Build Coastguard Worker case stg::Primitive::Encoding::UNSIGNED_INTEGER:
378*9e3b08aeSAndroid Build Coastguard Worker return Primitive::UNSIGNED_INTEGER;
379*9e3b08aeSAndroid Build Coastguard Worker case stg::Primitive::Encoding::SIGNED_CHARACTER:
380*9e3b08aeSAndroid Build Coastguard Worker return Primitive::SIGNED_CHARACTER;
381*9e3b08aeSAndroid Build Coastguard Worker case stg::Primitive::Encoding::UNSIGNED_CHARACTER:
382*9e3b08aeSAndroid Build Coastguard Worker return Primitive::UNSIGNED_CHARACTER;
383*9e3b08aeSAndroid Build Coastguard Worker case stg::Primitive::Encoding::REAL_NUMBER:
384*9e3b08aeSAndroid Build Coastguard Worker return Primitive::REAL_NUMBER;
385*9e3b08aeSAndroid Build Coastguard Worker case stg::Primitive::Encoding::COMPLEX_NUMBER:
386*9e3b08aeSAndroid Build Coastguard Worker return Primitive::COMPLEX_NUMBER;
387*9e3b08aeSAndroid Build Coastguard Worker case stg::Primitive::Encoding::UTF:
388*9e3b08aeSAndroid Build Coastguard Worker return Primitive::UTF;
389*9e3b08aeSAndroid Build Coastguard Worker }
390*9e3b08aeSAndroid Build Coastguard Worker }
391*9e3b08aeSAndroid Build Coastguard Worker
392*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(stg::BaseClass::Inheritance x)393*9e3b08aeSAndroid Build Coastguard Worker BaseClass::Inheritance Transform<MapId>::operator()(
394*9e3b08aeSAndroid Build Coastguard Worker stg::BaseClass::Inheritance x) {
395*9e3b08aeSAndroid Build Coastguard Worker switch (x) {
396*9e3b08aeSAndroid Build Coastguard Worker case stg::BaseClass::Inheritance::NON_VIRTUAL:
397*9e3b08aeSAndroid Build Coastguard Worker return BaseClass::NON_VIRTUAL;
398*9e3b08aeSAndroid Build Coastguard Worker case stg::BaseClass::Inheritance::VIRTUAL:
399*9e3b08aeSAndroid Build Coastguard Worker return BaseClass::VIRTUAL;
400*9e3b08aeSAndroid Build Coastguard Worker }
401*9e3b08aeSAndroid Build Coastguard Worker }
402*9e3b08aeSAndroid Build Coastguard Worker
403*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(stg::StructUnion::Kind x)404*9e3b08aeSAndroid Build Coastguard Worker StructUnion::Kind Transform<MapId>::operator()(stg::StructUnion::Kind x) {
405*9e3b08aeSAndroid Build Coastguard Worker switch (x) {
406*9e3b08aeSAndroid Build Coastguard Worker case stg::StructUnion::Kind::STRUCT:
407*9e3b08aeSAndroid Build Coastguard Worker return StructUnion::STRUCT;
408*9e3b08aeSAndroid Build Coastguard Worker case stg::StructUnion::Kind::UNION:
409*9e3b08aeSAndroid Build Coastguard Worker return StructUnion::UNION;
410*9e3b08aeSAndroid Build Coastguard Worker }
411*9e3b08aeSAndroid Build Coastguard Worker }
412*9e3b08aeSAndroid Build Coastguard Worker
413*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(stg::ElfSymbol::SymbolType x)414*9e3b08aeSAndroid Build Coastguard Worker ElfSymbol::SymbolType Transform<MapId>::operator()(
415*9e3b08aeSAndroid Build Coastguard Worker stg::ElfSymbol::SymbolType x) {
416*9e3b08aeSAndroid Build Coastguard Worker switch (x) {
417*9e3b08aeSAndroid Build Coastguard Worker case stg::ElfSymbol::SymbolType::NOTYPE:
418*9e3b08aeSAndroid Build Coastguard Worker return ElfSymbol::NOTYPE;
419*9e3b08aeSAndroid Build Coastguard Worker case stg::ElfSymbol::SymbolType::OBJECT:
420*9e3b08aeSAndroid Build Coastguard Worker return ElfSymbol::OBJECT;
421*9e3b08aeSAndroid Build Coastguard Worker case stg::ElfSymbol::SymbolType::FUNCTION:
422*9e3b08aeSAndroid Build Coastguard Worker return ElfSymbol::FUNCTION;
423*9e3b08aeSAndroid Build Coastguard Worker case stg::ElfSymbol::SymbolType::COMMON:
424*9e3b08aeSAndroid Build Coastguard Worker return ElfSymbol::COMMON;
425*9e3b08aeSAndroid Build Coastguard Worker case stg::ElfSymbol::SymbolType::TLS:
426*9e3b08aeSAndroid Build Coastguard Worker return ElfSymbol::TLS;
427*9e3b08aeSAndroid Build Coastguard Worker case stg::ElfSymbol::SymbolType::GNU_IFUNC:
428*9e3b08aeSAndroid Build Coastguard Worker return ElfSymbol::GNU_IFUNC;
429*9e3b08aeSAndroid Build Coastguard Worker }
430*9e3b08aeSAndroid Build Coastguard Worker }
431*9e3b08aeSAndroid Build Coastguard Worker
432*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(stg::ElfSymbol::Binding x)433*9e3b08aeSAndroid Build Coastguard Worker ElfSymbol::Binding Transform<MapId>::operator()(stg::ElfSymbol::Binding x) {
434*9e3b08aeSAndroid Build Coastguard Worker switch (x) {
435*9e3b08aeSAndroid Build Coastguard Worker case stg::ElfSymbol::Binding::GLOBAL:
436*9e3b08aeSAndroid Build Coastguard Worker return ElfSymbol::GLOBAL;
437*9e3b08aeSAndroid Build Coastguard Worker case stg::ElfSymbol::Binding::LOCAL:
438*9e3b08aeSAndroid Build Coastguard Worker return ElfSymbol::LOCAL;
439*9e3b08aeSAndroid Build Coastguard Worker case stg::ElfSymbol::Binding::WEAK:
440*9e3b08aeSAndroid Build Coastguard Worker return ElfSymbol::WEAK;
441*9e3b08aeSAndroid Build Coastguard Worker case stg::ElfSymbol::Binding::GNU_UNIQUE:
442*9e3b08aeSAndroid Build Coastguard Worker return ElfSymbol::GNU_UNIQUE;
443*9e3b08aeSAndroid Build Coastguard Worker }
444*9e3b08aeSAndroid Build Coastguard Worker }
445*9e3b08aeSAndroid Build Coastguard Worker
446*9e3b08aeSAndroid Build Coastguard Worker template <typename MapId>
operator ()(stg::ElfSymbol::Visibility x)447*9e3b08aeSAndroid Build Coastguard Worker ElfSymbol::Visibility Transform<MapId>::operator()(
448*9e3b08aeSAndroid Build Coastguard Worker stg::ElfSymbol::Visibility x) {
449*9e3b08aeSAndroid Build Coastguard Worker switch (x) {
450*9e3b08aeSAndroid Build Coastguard Worker case stg::ElfSymbol::Visibility::DEFAULT:
451*9e3b08aeSAndroid Build Coastguard Worker return ElfSymbol::DEFAULT;
452*9e3b08aeSAndroid Build Coastguard Worker case stg::ElfSymbol::Visibility::PROTECTED:
453*9e3b08aeSAndroid Build Coastguard Worker return ElfSymbol::PROTECTED;
454*9e3b08aeSAndroid Build Coastguard Worker case stg::ElfSymbol::Visibility::HIDDEN:
455*9e3b08aeSAndroid Build Coastguard Worker return ElfSymbol::HIDDEN;
456*9e3b08aeSAndroid Build Coastguard Worker case stg::ElfSymbol::Visibility::INTERNAL:
457*9e3b08aeSAndroid Build Coastguard Worker return ElfSymbol::INTERNAL;
458*9e3b08aeSAndroid Build Coastguard Worker }
459*9e3b08aeSAndroid Build Coastguard Worker }
460*9e3b08aeSAndroid Build Coastguard Worker
461*9e3b08aeSAndroid Build Coastguard Worker template <typename ProtoNode>
SortNodesById(google::protobuf::RepeatedPtrField<ProtoNode> & nodes)462*9e3b08aeSAndroid Build Coastguard Worker void SortNodesById(google::protobuf::RepeatedPtrField<ProtoNode>& nodes) {
463*9e3b08aeSAndroid Build Coastguard Worker const auto compare = [](const auto* lhs, const auto* rhs) {
464*9e3b08aeSAndroid Build Coastguard Worker return lhs->id() < rhs->id();
465*9e3b08aeSAndroid Build Coastguard Worker };
466*9e3b08aeSAndroid Build Coastguard Worker std::sort(nodes.pointer_begin(), nodes.pointer_end(), compare);
467*9e3b08aeSAndroid Build Coastguard Worker }
468*9e3b08aeSAndroid Build Coastguard Worker
469*9e3b08aeSAndroid Build Coastguard Worker template <typename ProtoNode>
SortNodesByName(google::protobuf::RepeatedPtrField<ProtoNode> & nodes)470*9e3b08aeSAndroid Build Coastguard Worker void SortNodesByName(google::protobuf::RepeatedPtrField<ProtoNode>& nodes) {
471*9e3b08aeSAndroid Build Coastguard Worker const auto compare = [](const auto* lhs, const auto* rhs) {
472*9e3b08aeSAndroid Build Coastguard Worker return std::forward_as_tuple(lhs->name(), lhs->id())
473*9e3b08aeSAndroid Build Coastguard Worker < std::forward_as_tuple(rhs->name(), rhs->id());
474*9e3b08aeSAndroid Build Coastguard Worker };
475*9e3b08aeSAndroid Build Coastguard Worker std::sort(nodes.pointer_begin(), nodes.pointer_end(), compare);
476*9e3b08aeSAndroid Build Coastguard Worker }
477*9e3b08aeSAndroid Build Coastguard Worker
SortMethodsByMangledName(google::protobuf::RepeatedPtrField<Method> & methods)478*9e3b08aeSAndroid Build Coastguard Worker void SortMethodsByMangledName(google::protobuf::RepeatedPtrField<Method>& methods) {
479*9e3b08aeSAndroid Build Coastguard Worker const auto compare = [](const Method* lhs, const Method* rhs) {
480*9e3b08aeSAndroid Build Coastguard Worker return std::forward_as_tuple(lhs->mangled_name(), lhs->id())
481*9e3b08aeSAndroid Build Coastguard Worker < std::forward_as_tuple(rhs->mangled_name(), rhs->id());
482*9e3b08aeSAndroid Build Coastguard Worker };
483*9e3b08aeSAndroid Build Coastguard Worker std::sort(methods.pointer_begin(), methods.pointer_end(), compare);
484*9e3b08aeSAndroid Build Coastguard Worker }
485*9e3b08aeSAndroid Build Coastguard Worker
SortElfSymbolsByVersionedName(google::protobuf::RepeatedPtrField<ElfSymbol> & elf_symbols)486*9e3b08aeSAndroid Build Coastguard Worker void SortElfSymbolsByVersionedName(
487*9e3b08aeSAndroid Build Coastguard Worker google::protobuf::RepeatedPtrField<ElfSymbol>& elf_symbols) {
488*9e3b08aeSAndroid Build Coastguard Worker const auto compare = [](const ElfSymbol* lhs, const ElfSymbol* rhs) {
489*9e3b08aeSAndroid Build Coastguard Worker // Sorting by:
490*9e3b08aeSAndroid Build Coastguard Worker //
491*9e3b08aeSAndroid Build Coastguard Worker // name
492*9e3b08aeSAndroid Build Coastguard Worker // version name
493*9e3b08aeSAndroid Build Coastguard Worker // ID as tie-breaker
494*9e3b08aeSAndroid Build Coastguard Worker //
495*9e3b08aeSAndroid Build Coastguard Worker // Note: symbols without version information will be ordered before
496*9e3b08aeSAndroid Build Coastguard Worker // versioned symbols of the same name.
497*9e3b08aeSAndroid Build Coastguard Worker return std::forward_as_tuple(lhs->name(), lhs->version_info().name(),
498*9e3b08aeSAndroid Build Coastguard Worker lhs->id())
499*9e3b08aeSAndroid Build Coastguard Worker < std::forward_as_tuple(rhs->name(), rhs->version_info().name(),
500*9e3b08aeSAndroid Build Coastguard Worker rhs->id());
501*9e3b08aeSAndroid Build Coastguard Worker };
502*9e3b08aeSAndroid Build Coastguard Worker std::sort(elf_symbols.pointer_begin(), elf_symbols.pointer_end(), compare);
503*9e3b08aeSAndroid Build Coastguard Worker }
504*9e3b08aeSAndroid Build Coastguard Worker
SortNodes(STG & stg)505*9e3b08aeSAndroid Build Coastguard Worker void SortNodes(STG& stg) {
506*9e3b08aeSAndroid Build Coastguard Worker SortNodesById(*stg.mutable_void_());
507*9e3b08aeSAndroid Build Coastguard Worker SortNodesById(*stg.mutable_variadic());
508*9e3b08aeSAndroid Build Coastguard Worker SortNodesById(*stg.mutable_pointer_reference());
509*9e3b08aeSAndroid Build Coastguard Worker SortNodesById(*stg.mutable_pointer_to_member());
510*9e3b08aeSAndroid Build Coastguard Worker SortNodesByName(*stg.mutable_typedef_());
511*9e3b08aeSAndroid Build Coastguard Worker SortNodesById(*stg.mutable_qualified());
512*9e3b08aeSAndroid Build Coastguard Worker SortNodesById(*stg.mutable_primitive());
513*9e3b08aeSAndroid Build Coastguard Worker SortNodesById(*stg.mutable_array());
514*9e3b08aeSAndroid Build Coastguard Worker SortNodesById(*stg.mutable_base_class());
515*9e3b08aeSAndroid Build Coastguard Worker SortMethodsByMangledName(*stg.mutable_method());
516*9e3b08aeSAndroid Build Coastguard Worker SortNodesByName(*stg.mutable_member());
517*9e3b08aeSAndroid Build Coastguard Worker SortNodesByName(*stg.mutable_struct_union());
518*9e3b08aeSAndroid Build Coastguard Worker SortNodesByName(*stg.mutable_enumeration());
519*9e3b08aeSAndroid Build Coastguard Worker SortNodesById(*stg.mutable_function());
520*9e3b08aeSAndroid Build Coastguard Worker SortElfSymbolsByVersionedName(*stg.mutable_elf_symbol());
521*9e3b08aeSAndroid Build Coastguard Worker }
522*9e3b08aeSAndroid Build Coastguard Worker
523*9e3b08aeSAndroid Build Coastguard Worker class HexPrinter : public google::protobuf::TextFormat::FastFieldValuePrinter {
PrintUInt32(uint32_t value,google::protobuf::TextFormat::BaseTextGenerator * generator) const524*9e3b08aeSAndroid Build Coastguard Worker void PrintUInt32(
525*9e3b08aeSAndroid Build Coastguard Worker uint32_t value,
526*9e3b08aeSAndroid Build Coastguard Worker google::protobuf::TextFormat::BaseTextGenerator* generator) const final {
527*9e3b08aeSAndroid Build Coastguard Worker std::ostringstream os;
528*9e3b08aeSAndroid Build Coastguard Worker // 0x01234567
529*9e3b08aeSAndroid Build Coastguard Worker os << "0x" << std::hex << std::setfill('0') << std::setw(8) << value;
530*9e3b08aeSAndroid Build Coastguard Worker generator->PrintString(os.str());
531*9e3b08aeSAndroid Build Coastguard Worker }
532*9e3b08aeSAndroid Build Coastguard Worker };
533*9e3b08aeSAndroid Build Coastguard Worker
534*9e3b08aeSAndroid Build Coastguard Worker class AnnotationHexPrinter : public google::protobuf::TextFormat::FastFieldValuePrinter {
535*9e3b08aeSAndroid Build Coastguard Worker public:
AnnotationHexPrinter(Describe & describe,const std::unordered_map<uint32_t,Id> & internal_id_by_external_id)536*9e3b08aeSAndroid Build Coastguard Worker AnnotationHexPrinter(
537*9e3b08aeSAndroid Build Coastguard Worker Describe& describe,
538*9e3b08aeSAndroid Build Coastguard Worker const std::unordered_map<uint32_t, Id>& internal_id_by_external_id)
539*9e3b08aeSAndroid Build Coastguard Worker : describe_(describe),
540*9e3b08aeSAndroid Build Coastguard Worker internal_id_by_external_id_(internal_id_by_external_id) {}
541*9e3b08aeSAndroid Build Coastguard Worker
542*9e3b08aeSAndroid Build Coastguard Worker private:
PrintUInt32(uint32_t value,google::protobuf::TextFormat::BaseTextGenerator * generator) const543*9e3b08aeSAndroid Build Coastguard Worker void PrintUInt32(
544*9e3b08aeSAndroid Build Coastguard Worker uint32_t value,
545*9e3b08aeSAndroid Build Coastguard Worker google::protobuf::TextFormat::BaseTextGenerator* generator) const final {
546*9e3b08aeSAndroid Build Coastguard Worker std::ostringstream os;
547*9e3b08aeSAndroid Build Coastguard Worker // 0x01234567 # Describe(0x01234567)
548*9e3b08aeSAndroid Build Coastguard Worker os << "0x" << std::hex << std::setfill('0') << std::setw(8) << value
549*9e3b08aeSAndroid Build Coastguard Worker << " # " << describe_(internal_id_by_external_id_.at(value));
550*9e3b08aeSAndroid Build Coastguard Worker generator->PrintString(os.str());
551*9e3b08aeSAndroid Build Coastguard Worker }
552*9e3b08aeSAndroid Build Coastguard Worker
553*9e3b08aeSAndroid Build Coastguard Worker Describe& describe_;
554*9e3b08aeSAndroid Build Coastguard Worker const std::unordered_map<uint32_t, Id>& internal_id_by_external_id_;
555*9e3b08aeSAndroid Build Coastguard Worker };
556*9e3b08aeSAndroid Build Coastguard Worker
557*9e3b08aeSAndroid Build Coastguard Worker const uint32_t kWrittenFormatVersion = 2;
558*9e3b08aeSAndroid Build Coastguard Worker
559*9e3b08aeSAndroid Build Coastguard Worker // Collection of fields which represent edges in the STG proto.
560*9e3b08aeSAndroid Build Coastguard Worker //
561*9e3b08aeSAndroid Build Coastguard Worker // This collection is used to register the AnnotationHexPrinter for each of the
562*9e3b08aeSAndroid Build Coastguard Worker // fields, which will print a description of the node in STG to which the edge
563*9e3b08aeSAndroid Build Coastguard Worker // points.
564*9e3b08aeSAndroid Build Coastguard Worker const std::array<const google::protobuf::FieldDescriptor*, 19> edge_descriptors = {
565*9e3b08aeSAndroid Build Coastguard Worker PointerReference::descriptor()->FindFieldByNumber(3),
566*9e3b08aeSAndroid Build Coastguard Worker PointerToMember::descriptor()->FindFieldByNumber(3),
567*9e3b08aeSAndroid Build Coastguard Worker Typedef::descriptor()->FindFieldByNumber(3),
568*9e3b08aeSAndroid Build Coastguard Worker Qualified::descriptor()->FindFieldByNumber(3),
569*9e3b08aeSAndroid Build Coastguard Worker Array::descriptor()->FindFieldByNumber(3),
570*9e3b08aeSAndroid Build Coastguard Worker BaseClass::descriptor()->FindFieldByNumber(2),
571*9e3b08aeSAndroid Build Coastguard Worker Method::descriptor()->FindFieldByNumber(5),
572*9e3b08aeSAndroid Build Coastguard Worker Member::descriptor()->FindFieldByNumber(3),
573*9e3b08aeSAndroid Build Coastguard Worker VariantMember::descriptor()->FindFieldByNumber(4),
574*9e3b08aeSAndroid Build Coastguard Worker StructUnion::Definition::descriptor()->FindFieldByNumber(2),
575*9e3b08aeSAndroid Build Coastguard Worker StructUnion::Definition::descriptor()->FindFieldByNumber(3),
576*9e3b08aeSAndroid Build Coastguard Worker StructUnion::Definition::descriptor()->FindFieldByNumber(4),
577*9e3b08aeSAndroid Build Coastguard Worker Enumeration::Definition::descriptor()->FindFieldByNumber(1),
578*9e3b08aeSAndroid Build Coastguard Worker Function::descriptor()->FindFieldByNumber(2),
579*9e3b08aeSAndroid Build Coastguard Worker Function::descriptor()->FindFieldByNumber(3),
580*9e3b08aeSAndroid Build Coastguard Worker ElfSymbol::descriptor()->FindFieldByNumber(10),
581*9e3b08aeSAndroid Build Coastguard Worker Interface::descriptor()->FindFieldByNumber(2),
582*9e3b08aeSAndroid Build Coastguard Worker Interface::descriptor()->FindFieldByNumber(3),
583*9e3b08aeSAndroid Build Coastguard Worker STG::descriptor()->FindFieldByNumber(2),
584*9e3b08aeSAndroid Build Coastguard Worker };
585*9e3b08aeSAndroid Build Coastguard Worker
586*9e3b08aeSAndroid Build Coastguard Worker } // namespace
587*9e3b08aeSAndroid Build Coastguard Worker
Write(const Id & root,google::protobuf::io::ZeroCopyOutputStream & os,bool annotate)588*9e3b08aeSAndroid Build Coastguard Worker void Writer::Write(const Id& root, google::protobuf::io::ZeroCopyOutputStream& os,
589*9e3b08aeSAndroid Build Coastguard Worker bool annotate) {
590*9e3b08aeSAndroid Build Coastguard Worker proto::STG stg;
591*9e3b08aeSAndroid Build Coastguard Worker StableId stable_id(graph_);
592*9e3b08aeSAndroid Build Coastguard Worker Transform<StableId> transform(graph_, stg, stable_id);
593*9e3b08aeSAndroid Build Coastguard Worker stg.set_root_id(transform(root));
594*9e3b08aeSAndroid Build Coastguard Worker SortNodes(stg);
595*9e3b08aeSAndroid Build Coastguard Worker stg.set_version(kWrittenFormatVersion);
596*9e3b08aeSAndroid Build Coastguard Worker
597*9e3b08aeSAndroid Build Coastguard Worker // Print
598*9e3b08aeSAndroid Build Coastguard Worker google::protobuf::TextFormat::Printer printer;
599*9e3b08aeSAndroid Build Coastguard Worker printer.SetDefaultFieldValuePrinter(new HexPrinter());
600*9e3b08aeSAndroid Build Coastguard Worker if (annotate) {
601*9e3b08aeSAndroid Build Coastguard Worker NameCache names;
602*9e3b08aeSAndroid Build Coastguard Worker Describe describe(graph_, names);
603*9e3b08aeSAndroid Build Coastguard Worker auto internal_id_by_external_id = transform.GetInternalIdByExternalIdMap();
604*9e3b08aeSAndroid Build Coastguard Worker for (const auto* descriptor : edge_descriptors) {
605*9e3b08aeSAndroid Build Coastguard Worker Check(printer.RegisterFieldValuePrinter(
606*9e3b08aeSAndroid Build Coastguard Worker descriptor,
607*9e3b08aeSAndroid Build Coastguard Worker new AnnotationHexPrinter(describe, internal_id_by_external_id)))
608*9e3b08aeSAndroid Build Coastguard Worker << "Failed to register annotation printer for descriptor: "
609*9e3b08aeSAndroid Build Coastguard Worker << descriptor->name();
610*9e3b08aeSAndroid Build Coastguard Worker }
611*9e3b08aeSAndroid Build Coastguard Worker Check(printer.Print(stg, &os)) << "Failed to write STG";
612*9e3b08aeSAndroid Build Coastguard Worker } else {
613*9e3b08aeSAndroid Build Coastguard Worker Check(printer.Print(stg, &os)) << "Failed to write STG";
614*9e3b08aeSAndroid Build Coastguard Worker }
615*9e3b08aeSAndroid Build Coastguard Worker }
616*9e3b08aeSAndroid Build Coastguard Worker
617*9e3b08aeSAndroid Build Coastguard Worker } // namespace proto
618*9e3b08aeSAndroid Build Coastguard Worker } // namespace stg
619