1 // Copyright (C) 2016 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "abi_wrappers.h"
16
17 #include <header_abi_util.h>
18
19 #include <limits.h>
20 #include <stdlib.h>
21 #include <clang/Tooling/Core/QualTypeNames.h>
22 #include <clang/Index/CodegenNameGenerator.h>
23
24 #include <string>
25
26 using namespace abi_wrapper;
27
ABIWrapper(clang::MangleContext * mangle_contextp,clang::ASTContext * ast_contextp,const clang::CompilerInstance * cip)28 ABIWrapper::ABIWrapper(
29 clang::MangleContext *mangle_contextp,
30 clang::ASTContext *ast_contextp,
31 const clang::CompilerInstance *cip)
32 : cip_(cip),
33 mangle_contextp_(mangle_contextp),
34 ast_contextp_(ast_contextp) { }
35
GetDeclSourceFile(const clang::Decl * decl,const clang::CompilerInstance * cip)36 std::string ABIWrapper::GetDeclSourceFile(const clang::Decl *decl,
37 const clang::CompilerInstance *cip) {
38 clang::SourceManager &sm = cip->getSourceManager();
39 clang::SourceLocation location = decl->getLocation();
40 // We need to use the expansion location to identify whether we should recurse
41 // into the AST Node or not. For eg: macros specifying LinkageSpecDecl can
42 // have their spelling location defined somewhere outside a source / header
43 // file belonging to a library. This should not allow the AST node to be
44 // skipped. Its expansion location will still be the source-file / header
45 // belonging to the library.
46 clang::SourceLocation expansion_location = sm.getExpansionLoc(location);
47 llvm::StringRef file_name = sm.getFilename(expansion_location);
48 std::string file_name_adjusted = "";
49 char file_abs_path[PATH_MAX];
50 if (realpath(file_name.str().c_str(), file_abs_path) == nullptr) {
51 return "";
52 }
53 return file_abs_path;
54 }
55
AccessClangToDump(const clang::AccessSpecifier sp) const56 abi_dump::AccessSpecifier ABIWrapper::AccessClangToDump(
57 const clang::AccessSpecifier sp) const {
58 switch (sp) {
59 case clang::AS_private: {
60 return abi_dump::AccessSpecifier::private_access;
61 break;
62 }
63 case clang::AS_protected: {
64 return abi_dump::AccessSpecifier::protected_access;
65 break;
66 }
67 default: {
68 return abi_dump::AccessSpecifier::public_access;
69 break;
70 }
71 }
72 }
73
74 // Dumping the size and alignment is optional. This is since clang can lazily
75 // instantiate records as incomplete and therefore their sizes 'may' not be
76 // computable. b/62307940
SetupBasicTypeAbi(abi_dump::BasicTypeAbi * type_abi,const clang::QualType type,bool dump_size) const77 bool ABIWrapper::SetupBasicTypeAbi(abi_dump::BasicTypeAbi *type_abi,
78 const clang::QualType type,
79 bool dump_size) const {
80 if (!type_abi) {
81 return false;
82 }
83 const clang::QualType canonical_type = type.getCanonicalType();
84 type_abi->set_name(QualTypeToString(canonical_type));
85 // Cannot determine the size and alignment for template parameter dependent
86 // types as well as incomplete types.
87 const clang::Type *base_type = canonical_type.getTypePtr();
88 clang::Type::TypeClass type_class = base_type->getTypeClass();
89 // Temporary Hack for auto type sizes. Not determinable.
90 if (dump_size && base_type && !(base_type->isDependentType()) &&
91 !(base_type->isIncompleteType()) && (type_class != clang::Type::Auto)) {
92 std::pair<clang::CharUnits, clang::CharUnits> size_and_alignment =
93 ast_contextp_->getTypeInfoInChars(canonical_type);
94 int64_t size = size_and_alignment.first.getQuantity();
95 int64_t alignment = size_and_alignment.second.getQuantity();
96 type_abi->set_size(size);
97 type_abi->set_alignment(alignment);
98 }
99 return true;
100 }
101
SetupBasicNamedAndTypedDecl(abi_dump::BasicNamedAndTypedDecl * basic_named_and_typed_decl,const clang::QualType type,const std::string & name,const clang::AccessSpecifier & access,std::string key,bool dump_size) const102 bool ABIWrapper::SetupBasicNamedAndTypedDecl(
103 abi_dump::BasicNamedAndTypedDecl *basic_named_and_typed_decl,
104 const clang::QualType type, const std::string &name,
105 const clang::AccessSpecifier &access, std::string key,
106 bool dump_size) const {
107 if (!basic_named_and_typed_decl) {
108 return false;
109 }
110 abi_dump::AccessSpecifier access_dump = AccessClangToDump(access);
111 basic_named_and_typed_decl->set_name(name);
112 basic_named_and_typed_decl->set_access(access_dump);
113 if (key != "") {
114 basic_named_and_typed_decl->set_linker_set_key(key);
115 }
116 return SetupBasicTypeAbi(basic_named_and_typed_decl->mutable_type_abi(),
117 type, dump_size);
118 }
119
ShouldDumpSize(clang::QualType qt)120 static bool ShouldDumpSize(clang::QualType qt) {
121 const clang::Type *type_ptr = qt.getTypePtr();
122 assert(type_ptr != nullptr);
123 if (type_ptr->isBuiltinType() || type_ptr->isPointerType()) {
124 return true;
125 }
126 return false;
127 }
128
GetTypeLinkageName(const clang::Type * typep) const129 std::string ABIWrapper::GetTypeLinkageName(const clang::Type *typep) const {
130 assert(typep != nullptr);
131 clang::QualType qt = typep->getCanonicalTypeInternal();
132 return QualTypeToString(qt);
133 }
134
GetMangledNameDecl(const clang::NamedDecl * decl,clang::MangleContext * mangle_contextp)135 std::string ABIWrapper::GetMangledNameDecl(
136 const clang::NamedDecl *decl, clang::MangleContext *mangle_contextp) {
137 if (!mangle_contextp->shouldMangleDeclName(decl)) {
138 clang::IdentifierInfo *identifier = decl->getIdentifier();
139 return identifier ? identifier->getName() : "";
140 }
141 std::string mangled_name;
142 llvm::raw_string_ostream ostream(mangled_name);
143 mangle_contextp->mangleName(decl, ostream);
144 ostream.flush();
145 return mangled_name;
146 }
147
SetupTemplateParamNames(abi_dump::TemplateInfo * tinfo,clang::TemplateParameterList * pl) const148 bool ABIWrapper::SetupTemplateParamNames(
149 abi_dump::TemplateInfo *tinfo,
150 clang::TemplateParameterList *pl) const {
151 if (tinfo->elements_size() > 0) {
152 return true;
153 }
154
155 clang::TemplateParameterList::iterator template_it = pl->begin();
156 while (template_it != pl->end()) {
157 abi_dump::TemplateElement *template_parameterp =
158 tinfo->add_elements();
159 if (!template_parameterp) {
160 return false;
161 }
162 abi_dump::TemplateElement::BasicTemplateElementAbi *basic_abi =
163 template_parameterp->mutable_basic_abi();
164 if (!basic_abi) {
165 return false;
166 }
167 std::string name = (*template_it)->getName();
168 basic_abi->set_name(name);
169 // TODO : Default arg ?
170 basic_abi->set_linker_set_key(name);
171 template_it++;
172 }
173 return true;
174 }
175
GetTagDeclQualifiedName(const clang::TagDecl * decl) const176 std::string ABIWrapper::GetTagDeclQualifiedName(
177 const clang::TagDecl *decl) const {
178 if (decl->getTypedefNameForAnonDecl()) {
179 return decl->getTypedefNameForAnonDecl()->getQualifiedNameAsString();
180 }
181 return decl->getQualifiedNameAsString();
182 }
183
SetupTemplateArguments(abi_dump::TemplateInfo * tinfo,const clang::TemplateArgumentList * tl) const184 bool ABIWrapper::SetupTemplateArguments(
185 abi_dump::TemplateInfo *tinfo,
186 const clang::TemplateArgumentList *tl) const {
187 for (int i = 0; i < tl->size(); i++) {
188 const clang::TemplateArgument &arg = (*tl)[i];
189 //TODO: More comprehensive checking needed.
190 if (arg.getKind() != clang::TemplateArgument::Type) {
191 continue;
192 }
193 clang::QualType type = arg.getAsType();
194 abi_dump::TemplateElement *template_parameterp =
195 tinfo->add_elements();
196 if (!template_parameterp) {
197 return false;
198 }
199 abi_dump::TemplateElement::BasicTemplateElementAbi *basic_abi =
200 template_parameterp->mutable_basic_abi();
201 if (!basic_abi || !SetupBasicTypeAbi(basic_abi->mutable_type_abi(), type,
202 false)) {
203 return false;
204 }
205 // TODO : default arg
206 basic_abi->set_linker_set_key(QualTypeToString(type));
207 }
208 return true;
209 }
210
QualTypeToString(const clang::QualType & sweet_qt) const211 std::string ABIWrapper::QualTypeToString(
212 const clang::QualType &sweet_qt) const {
213 const clang::QualType salty_qt = sweet_qt.getCanonicalType();
214 // clang::TypeName::getFullyQualifiedName removes the part of the type related
215 // to it being a template parameter. Don't use it for dependent types.
216 if (salty_qt.getTypePtr()->isDependentType()) {
217 return salty_qt.getAsString();
218 }
219 return clang::TypeName::getFullyQualifiedName(salty_qt, *ast_contextp_);
220 }
221
FunctionDeclWrapper(clang::MangleContext * mangle_contextp,clang::ASTContext * ast_contextp,const clang::CompilerInstance * compiler_instance_p,const clang::FunctionDecl * decl)222 FunctionDeclWrapper::FunctionDeclWrapper(
223 clang::MangleContext *mangle_contextp,
224 clang::ASTContext *ast_contextp,
225 const clang::CompilerInstance *compiler_instance_p,
226 const clang::FunctionDecl *decl)
227 : ABIWrapper(mangle_contextp, ast_contextp, compiler_instance_p),
228 function_decl_(decl) { }
229
SetupFunctionParameters(abi_dump::FunctionDecl * functionp) const230 bool FunctionDeclWrapper::SetupFunctionParameters(
231 abi_dump::FunctionDecl *functionp) const {
232 clang::FunctionDecl::param_const_iterator param_it =
233 function_decl_->param_begin();
234 while (param_it != function_decl_->param_end()) {
235 abi_dump::ParamDecl *function_fieldp = functionp->add_parameters();
236 if (!function_fieldp) {
237 llvm::errs() << "Couldn't add parameter to method. Aborting\n";
238 return false;
239 }
240 // The linker set key is blank since that shows up in the mangled name.
241 bool has_default_arg = (*param_it)->hasDefaultArg();
242 clang::QualType param_qt = (*param_it)->getType();
243 bool should_dump_size = ShouldDumpSize(param_qt);
244 if (!SetupBasicNamedAndTypedDecl(
245 function_fieldp->mutable_basic_abi(),
246 (*param_it)->getType(), (*param_it)->getName(),
247 (*param_it)->getAccess(), has_default_arg ? "true" : "false",
248 should_dump_size)) {
249 return false;
250 }
251 function_fieldp->set_default_arg(has_default_arg);
252 param_it++;
253 }
254 return true;
255 }
256
SetupFunction(abi_dump::FunctionDecl * functionp,const std::string & source_file) const257 bool FunctionDeclWrapper::SetupFunction(abi_dump::FunctionDecl *functionp,
258 const std::string &source_file) const {
259 // Go through all the parameters in the method and add them to the fields.
260 // Also get the fully qualfied name.
261 functionp->set_source_file(source_file);
262 // Combine the function name and return type to form a NamedAndTypedDecl
263 clang::QualType return_type = function_decl_->getReturnType();
264 bool should_dump_size = ShouldDumpSize(return_type);
265 return SetupBasicNamedAndTypedDecl(
266 functionp->mutable_basic_abi(),
267 return_type, function_decl_->getQualifiedNameAsString(),
268 function_decl_->getAccess(), "", should_dump_size) &&
269 SetupTemplateInfo(functionp) && SetupFunctionParameters(functionp);
270 }
271
SetupTemplateInfo(abi_dump::FunctionDecl * functionp) const272 bool FunctionDeclWrapper::SetupTemplateInfo(
273 abi_dump::FunctionDecl *functionp) const {
274 switch (function_decl_->getTemplatedKind()) {
275 case clang::FunctionDecl::TK_FunctionTemplate: {
276 clang::FunctionTemplateDecl *template_decl =
277 function_decl_->getDescribedFunctionTemplate();
278 if (template_decl) {
279 clang::TemplateParameterList *template_parameter_list =
280 template_decl->getTemplateParameters();
281 if (template_parameter_list &&
282 !SetupTemplateParamNames(functionp->mutable_template_info(),
283 template_parameter_list)) {
284 return false;
285 }
286 }
287 break;
288 }
289 case clang::FunctionDecl::TK_FunctionTemplateSpecialization: {
290 const clang::TemplateArgumentList *arg_list =
291 function_decl_->getTemplateSpecializationArgs();
292 if (arg_list &&
293 !SetupTemplateArguments(functionp->mutable_template_info(),
294 arg_list)) {
295 return false;
296 }
297 break;
298 }
299 default: {
300 break;
301 }
302 }
303 return true;
304 }
305
306 std::unique_ptr<abi_dump::FunctionDecl>
GetFunctionDecl() const307 FunctionDeclWrapper::GetFunctionDecl() const {
308 std::unique_ptr<abi_dump::FunctionDecl> abi_decl(
309 new abi_dump::FunctionDecl());
310 std::string source_file = GetDeclSourceFile(function_decl_, cip_);
311 if (!SetupFunction(abi_decl.get(), source_file)) {
312 return nullptr;
313 }
314 return abi_decl;
315 }
316
RecordDeclWrapper(clang::MangleContext * mangle_contextp,clang::ASTContext * ast_contextp,const clang::CompilerInstance * compiler_instance_p,const clang::RecordDecl * decl)317 RecordDeclWrapper::RecordDeclWrapper(
318 clang::MangleContext *mangle_contextp,
319 clang::ASTContext *ast_contextp,
320 const clang::CompilerInstance *compiler_instance_p,
321 const clang::RecordDecl *decl)
322 : ABIWrapper(mangle_contextp, ast_contextp, compiler_instance_p),
323 record_decl_(decl) { }
324
SetupRecordFields(abi_dump::RecordDecl * recordp) const325 bool RecordDeclWrapper::SetupRecordFields(abi_dump::RecordDecl *recordp) const {
326 clang::RecordDecl::field_iterator field = record_decl_->field_begin();
327 while (field != record_decl_->field_end()) {
328 abi_dump::RecordFieldDecl *record_fieldp = recordp->add_fields();
329 if (!record_fieldp) {
330 llvm::errs() << " Couldn't add record field: " << field->getName()
331 << " to reference dump\n";
332 return false;
333 }
334 if (!SetupBasicNamedAndTypedDecl(record_fieldp->mutable_basic_abi(),
335 field->getType(), field->getName(),
336 field->getAccess(), "", true)) {
337 return false;
338 }
339 field++;
340 }
341 return true;
342 }
343
SetupCXXBases(abi_dump::RecordDecl * cxxp,const clang::CXXRecordDecl * cxx_record_decl) const344 bool RecordDeclWrapper::SetupCXXBases(
345 abi_dump::RecordDecl *cxxp,
346 const clang::CXXRecordDecl *cxx_record_decl) const {
347 assert(cxx_record_decl != nullptr);
348 clang::CXXRecordDecl::base_class_const_iterator base_class =
349 cxx_record_decl->bases_begin();
350 while (base_class != cxx_record_decl->bases_end()) {
351 abi_dump::CXXBaseSpecifier *base_specifierp = cxxp->add_base_specifiers();
352 if (!base_specifierp) {
353 llvm::errs() << " Couldn't add base specifier to reference dump\n";
354 return false;
355 }
356 std::string name = QualTypeToString(base_class->getType());
357 bool is_virtual = base_class->isVirtual();
358 if (!SetupBasicNamedAndTypedDecl(base_specifierp->mutable_basic_abi(),
359 base_class->getType(),
360 "", base_class->getAccessSpecifier(),
361 "", false)) {
362 return false;
363 }
364 base_specifierp->set_is_virtual(is_virtual);
365 base_class++;
366 }
367 return true;
368 }
369
SetupRecordVTable(abi_dump::RecordDecl * record_declp,const clang::CXXRecordDecl * cxx_record_decl) const370 bool RecordDeclWrapper::SetupRecordVTable(
371 abi_dump::RecordDecl *record_declp,
372 const clang::CXXRecordDecl *cxx_record_decl) const {
373 assert(cxx_record_decl != nullptr);
374 clang::VTableContextBase *base_vtable_contextp =
375 ast_contextp_->getVTableContext();
376 const clang::Type *typep = cxx_record_decl->getTypeForDecl();
377 if (!base_vtable_contextp || !typep) {
378 return false;
379 }
380 // Skip Microsoft ABI.
381 clang::ItaniumVTableContext *itanium_vtable_contextp =
382 llvm::dyn_cast<clang::ItaniumVTableContext>(base_vtable_contextp);
383 if (!itanium_vtable_contextp || !cxx_record_decl->isPolymorphic() ||
384 typep->isDependentType() || typep->isIncompleteType()) {
385 return true;
386 }
387 const clang::VTableLayout &vtable_layout =
388 itanium_vtable_contextp->getVTableLayout(cxx_record_decl);
389 abi_dump::VTableLayout *vtablep = record_declp->mutable_vtable_layout();
390 if (!vtablep) {
391 return false;
392 }
393 for (const auto &vtable_component : vtable_layout.vtable_components()) {
394 abi_dump::VTableComponent *added_vtable_component =
395 vtablep->add_vtable_components();
396 if (!added_vtable_component ||
397 !SetupRecordVTableComponent(added_vtable_component, vtable_component)) {
398 return false;
399 }
400 }
401 return true;
402 }
403
SetupRecordVTableComponent(abi_dump::VTableComponent * added_vtable_component,const clang::VTableComponent & vtable_component) const404 bool RecordDeclWrapper::SetupRecordVTableComponent(
405 abi_dump::VTableComponent *added_vtable_component,
406 const clang::VTableComponent &vtable_component) const {
407 assert(added_vtable_component != nullptr);
408 abi_dump::VTableComponent_Kind kind = abi_dump::VTableComponent_Kind_RTTI;
409 std::string mangled_component_name = "";
410 llvm::raw_string_ostream ostream(mangled_component_name);
411 int64_t value = 0;
412 clang::VTableComponent::Kind clang_component_kind =
413 vtable_component.getKind();
414 switch (clang_component_kind) {
415 case clang::VTableComponent::CK_VCallOffset:
416 kind = abi_dump::VTableComponent_Kind_VCallOffset;
417 value = vtable_component.getVCallOffset().getQuantity();
418 break;
419 case clang::VTableComponent::CK_VBaseOffset:
420 kind = abi_dump::VTableComponent_Kind_VBaseOffset;
421 value = vtable_component.getVBaseOffset().getQuantity();
422 break;
423 case clang::VTableComponent::CK_OffsetToTop:
424 kind = abi_dump::VTableComponent_Kind_OffsetToTop;
425 value = vtable_component.getOffsetToTop().getQuantity();
426 break;
427 case clang::VTableComponent::CK_RTTI:
428 {
429 kind = abi_dump::VTableComponent_Kind_RTTI;
430 const clang::CXXRecordDecl *rtti_decl =
431 vtable_component.getRTTIDecl();
432 assert(rtti_decl != nullptr);
433 mangled_component_name =
434 ABIWrapper::GetTypeLinkageName(rtti_decl->getTypeForDecl());
435 }
436 break;
437 case clang::VTableComponent::CK_FunctionPointer:
438 case clang::VTableComponent::CK_CompleteDtorPointer:
439 case clang::VTableComponent::CK_DeletingDtorPointer:
440 case clang::VTableComponent::CK_UnusedFunctionPointer:
441 {
442 const clang::CXXMethodDecl *method_decl =
443 vtable_component.getFunctionDecl();
444 assert(method_decl != nullptr);
445 switch (clang_component_kind) {
446 case clang::VTableComponent::CK_FunctionPointer:
447 kind = abi_dump::VTableComponent_Kind_FunctionPointer;
448 mangled_component_name = GetMangledNameDecl(method_decl,
449 mangle_contextp_);
450 break;
451 case clang::VTableComponent::CK_CompleteDtorPointer:
452 kind = abi_dump::VTableComponent_Kind_CompleteDtorPointer;
453 mangle_contextp_->mangleCXXDtor(
454 vtable_component.getDestructorDecl(),
455 clang::CXXDtorType::Dtor_Complete, ostream);
456 ostream.flush();
457
458 break;
459 case clang::VTableComponent::CK_DeletingDtorPointer:
460 kind = abi_dump::VTableComponent_Kind_DeletingDtorPointer;
461 mangle_contextp_->mangleCXXDtor(
462 vtable_component.getDestructorDecl(),
463 clang::CXXDtorType::Dtor_Deleting, ostream);
464 ostream.flush();
465 break;
466 case clang::VTableComponent::CK_UnusedFunctionPointer:
467 kind = abi_dump::VTableComponent_Kind_UnusedFunctionPointer;
468 default:
469 break;
470 }
471 }
472 break;
473 default:
474 return false;
475 }
476 added_vtable_component->set_kind(kind);
477 added_vtable_component->set_component_value(value);
478 added_vtable_component->set_mangled_component_name(mangled_component_name);
479 return true;
480 }
481
SetupTemplateInfo(abi_dump::RecordDecl * record_declp,const clang::CXXRecordDecl * cxx_record_decl) const482 bool RecordDeclWrapper::SetupTemplateInfo(
483 abi_dump::RecordDecl *record_declp,
484 const clang::CXXRecordDecl *cxx_record_decl) const {
485 assert(cxx_record_decl != nullptr);
486 if (cxx_record_decl->isTemplateDecl()) {
487 clang::ClassTemplateDecl *template_decl =
488 cxx_record_decl->getDescribedClassTemplate();
489 if (template_decl) {
490 clang::TemplateParameterList *template_parameter_list =
491 template_decl->getTemplateParameters();
492 if (template_parameter_list &&
493 !SetupTemplateParamNames(record_declp->mutable_template_info(),
494 template_parameter_list)) {
495 return false;
496 }
497 }
498 } else {
499 const clang::ClassTemplateSpecializationDecl *specialization_decl =
500 clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(
501 cxx_record_decl);
502 if(specialization_decl) {
503 const clang::TemplateArgumentList *arg_list =
504 &specialization_decl->getTemplateArgs();
505 if (arg_list &&
506 !SetupTemplateArguments(record_declp->mutable_template_info(),
507 arg_list)) {
508 return false;
509 }
510 }
511 }
512 return true;
513 }
514
SetupRecordInfo(abi_dump::RecordDecl * record_declp,const std::string & source_file) const515 bool RecordDeclWrapper::SetupRecordInfo(abi_dump::RecordDecl *record_declp,
516 const std::string &source_file) const {
517 std::string qualified_name = GetTagDeclQualifiedName(record_decl_);
518 const clang::Type *basic_type = nullptr;
519 if (!(basic_type = record_decl_->getTypeForDecl())) {
520 return false;
521 }
522 std::string mangled_name = ABIWrapper::GetTypeLinkageName(basic_type);
523 clang::QualType type = basic_type->getCanonicalTypeInternal();
524 std::string linker_key = (mangled_name == "") ? qualified_name : mangled_name;
525 if (!SetupBasicNamedAndTypedDecl(record_declp->mutable_basic_abi(),
526 type, qualified_name,
527 record_decl_->getAccess(), linker_key,
528 true)) {
529 return false;
530 }
531 record_declp->set_mangled_record_name(mangled_name);
532 record_declp->set_source_file(source_file);
533 return true;
534 }
535
SetupCXXRecordInfo(abi_dump::RecordDecl * record_declp) const536 bool RecordDeclWrapper::SetupCXXRecordInfo(
537 abi_dump::RecordDecl *record_declp) const {
538 const clang::CXXRecordDecl *cxx_record_decl =
539 clang::dyn_cast<clang::CXXRecordDecl>(record_decl_);
540 if (!cxx_record_decl) {
541 return true;
542 }
543 return SetupTemplateInfo(record_declp, cxx_record_decl) &&
544 SetupCXXBases(record_declp, cxx_record_decl) &&
545 SetupRecordVTable(record_declp, cxx_record_decl);
546 }
547
GetRecordDecl() const548 std::unique_ptr<abi_dump::RecordDecl> RecordDeclWrapper::GetRecordDecl() const {
549 std::unique_ptr<abi_dump::RecordDecl> abi_decl(new abi_dump::RecordDecl());
550 std::string source_file = GetDeclSourceFile(record_decl_, cip_);
551 abi_dump::RecordDecl *record_declp = abi_decl.get();
552 if (!SetupRecordInfo(record_declp, source_file) ||
553 !SetupRecordFields(record_declp) ||
554 !SetupCXXRecordInfo(abi_decl.get())) {
555 llvm::errs() << "Setting up CXX Bases / Template Info failed\n";
556 return nullptr;
557 }
558 return abi_decl;
559 }
560
EnumDeclWrapper(clang::MangleContext * mangle_contextp,clang::ASTContext * ast_contextp,const clang::CompilerInstance * compiler_instance_p,const clang::EnumDecl * decl)561 EnumDeclWrapper::EnumDeclWrapper(
562 clang::MangleContext *mangle_contextp,
563 clang::ASTContext *ast_contextp,
564 const clang::CompilerInstance *compiler_instance_p,
565 const clang::EnumDecl *decl)
566 : ABIWrapper(mangle_contextp, ast_contextp, compiler_instance_p),
567 enum_decl_(decl) { }
568
SetupEnumFields(abi_dump::EnumDecl * enump) const569 bool EnumDeclWrapper::SetupEnumFields(abi_dump::EnumDecl *enump) const {
570 clang::EnumDecl::enumerator_iterator enum_it = enum_decl_->enumerator_begin();
571 while (enum_it != enum_decl_->enumerator_end()) {
572 abi_dump::EnumFieldDecl *enum_fieldp = enump->add_enum_fields();
573 std::string name = enum_it->getQualifiedNameAsString();
574 uint64_t field_value = enum_it->getInitVal().getExtValue();
575 if (!enum_fieldp ||
576 !SetupBasicNamedAndTypedDecl(enum_fieldp->mutable_basic_abi(),
577 enum_it->getType(), name,
578 enum_it->getAccess(),
579 std::to_string(field_value), true)) {
580 return false;
581 }
582 enum_fieldp->set_enum_field_value(field_value);
583 enum_it++;
584 }
585 return true;
586 }
587
SetupEnum(abi_dump::EnumDecl * enump,const std::string & source_file) const588 bool EnumDeclWrapper::SetupEnum(abi_dump::EnumDecl *enump,
589 const std::string &source_file) const {
590 std::string enum_name = GetTagDeclQualifiedName(enum_decl_);
591 clang::QualType enum_type = enum_decl_->getIntegerType();
592 if (!SetupBasicNamedAndTypedDecl(enump->mutable_basic_abi(), enum_type,
593 enum_name, enum_decl_->getAccess(),
594 enum_name, true) ||
595 !SetupEnumFields(enump)) {
596 return false;
597 }
598 enump->set_source_file(source_file);
599 return true;
600 }
601
GetEnumDecl() const602 std::unique_ptr<abi_dump::EnumDecl> EnumDeclWrapper::GetEnumDecl() const {
603 std::unique_ptr<abi_dump::EnumDecl> abi_decl(new abi_dump::EnumDecl());
604 std::string source_file = GetDeclSourceFile(enum_decl_, cip_);
605
606 if (!SetupEnum(abi_decl.get(), source_file)) {
607 llvm::errs() << "Setting up Enum fields failed\n";
608 return nullptr;
609 }
610 return abi_decl;
611 }
612
GlobalVarDeclWrapper(clang::MangleContext * mangle_contextp,clang::ASTContext * ast_contextp,const clang::CompilerInstance * compiler_instance_p,const clang::VarDecl * decl)613 GlobalVarDeclWrapper::GlobalVarDeclWrapper(
614 clang::MangleContext *mangle_contextp,
615 clang::ASTContext *ast_contextp,
616 const clang::CompilerInstance *compiler_instance_p,
617 const clang::VarDecl *decl)
618 : ABIWrapper(mangle_contextp, ast_contextp, compiler_instance_p),
619 global_var_decl_(decl) { }
620
SetupGlobalVar(abi_dump::GlobalVarDecl * global_varp,const std::string & source_file) const621 bool GlobalVarDeclWrapper::SetupGlobalVar(
622 abi_dump::GlobalVarDecl *global_varp,
623 const std::string &source_file) const {
624 // Temporary fix : clang segfaults on trying to mangle global variable which
625 // is a dependent sized array type.
626 std::string qualified_name = global_var_decl_->getQualifiedNameAsString();
627 std::string mangled_name =
628 GetMangledNameDecl(global_var_decl_, mangle_contextp_);
629 if (!SetupBasicNamedAndTypedDecl(
630 global_varp->mutable_basic_abi(),global_var_decl_->getType(),
631 qualified_name, global_var_decl_->getAccess(),
632 mangled_name, true)) {
633 return false;
634 }
635 global_varp->set_source_file(source_file);
636 return true;
637 }
638
639 std::unique_ptr<abi_dump::GlobalVarDecl>
GetGlobalVarDecl() const640 GlobalVarDeclWrapper::GetGlobalVarDecl() const {
641 std::unique_ptr<abi_dump::GlobalVarDecl>
642 abi_decl(new abi_dump::GlobalVarDecl);
643 std::string source_file = GetDeclSourceFile(global_var_decl_, cip_);
644 if (!SetupGlobalVar(abi_decl.get(), source_file)) {
645 return nullptr;
646 }
647 return abi_decl;
648 }
649