source: src/SymTab/Demangle.cc@ 0589e83

Last change on this file since 0589e83 was 0589e83, checked in by Andrew Beach <ajbeach@…>, 2 years ago

The demangler now uses the compiler's genType. The only difference I can find is that the demangler genType wrote functions ': RET_TYPE' instead of the C style. If this or a different change turns out to be imported it will have to be replicated post-translation.

  • Property mode set to 100644
File size: 12.1 KB
RevLine 
[d1e0979]1//
2// Cforall Version 1.0.0 Copyright (C) 2018 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
[c0af102]7// Demangle.cc -- Convert a mangled name into a human readable name.
[d1e0979]8//
9// Author : Rob Schluntz
10// Created On : Thu Jul 19 12:52:41 2018
[c649d2c]11// Last Modified By : Andrew Beach
12// Last Modified On : Mon Nov 6 15:59:00 2023
13// Update Count : 12
[d1e0979]14//
15
16#include <algorithm>
17#include <sstream>
18
19#include "CodeGen/GenType.h"
[c649d2c]20#include "CodeGen/OperatorTable.h"
[d1e0979]21#include "Common/PassVisitor.h"
[8abca06]22#include "Common/utility.h" // isPrefix
[d1e0979]23#include "Mangler.h"
24#include "SynTree/Type.h"
25#include "SynTree/Declaration.h"
26
[04c77791]27#define DEBUG
[d1e0979]28#ifdef DEBUG
29#define PRINT(x) x
30#else
31#define PRINT(x) {}
32#endif
33
34namespace SymTab {
35 namespace Mangler {
36 namespace {
[c20fafd]37 struct StringView {
38 private:
39 std::string str;
40 size_t idx = 0;
41 // typedef Type * (StringView::*parser)(Type::Qualifiers);
42 typedef std::function<Type * (Type::Qualifiers)> parser;
43 std::vector<std::pair<std::string, parser>> parsers;
44 public:
45 StringView(const std::string & str);
46
47 bool done() const { return idx >= str.size(); }
48 char cur() const { assert(! done()); return str[idx]; }
49
50 bool expect(char ch) { return str[idx++] == ch; }
51 void next(size_t inc = 1) { idx += inc; }
52
53 /// determines if `pref` is a prefix of `str`
54 bool isPrefix(const std::string & pref);
55 bool extractNumber(size_t & out);
56 bool extractName(std::string & out);
57 bool stripMangleName(std::string & name);
58
59 Type * parseFunction(Type::Qualifiers tq);
60 Type * parseTuple(Type::Qualifiers tq);
61 Type * parseVoid(Type::Qualifiers tq);
62 Type * parsePointer(Type::Qualifiers tq);
[2f9768f]63 Type * parseArray(Type::Qualifiers tq);
[c20fafd]64 Type * parseStruct(Type::Qualifiers tq);
[38587bc]65 Type * parseUnion(Type::Qualifiers tq);
66 Type * parseEnum(Type::Qualifiers tq);
[efa8b6a]67 Type * parseType(Type::Qualifiers tq);
[c20fafd]68
69 Type * parseType();
70 bool parse(std::string & name, Type *& type);
71 };
72
73 StringView::StringView(const std::string & str) : str(str) {
74 // basic types
75 for (size_t k = 0; k < BasicType::NUMBER_OF_BASIC_TYPES; ++k) {
[8316a49]76 parsers.emplace_back(Encoding::basicTypes[k], [k](Type::Qualifiers tq) {
[c20fafd]77 PRINT( std::cerr << "basic type: " << k << std::endl; )
78 return new BasicType(tq, (BasicType::Kind)k);
79 });
80 }
[04c77791]81 // type variable types
82 for (size_t k = 0; k < TypeDecl::NUMBER_OF_KINDS; ++k) {
[b66d14a]83 static const std::string typeVariableNames[] = { "DT", "DST", "OT", "FT", "TT", "ALT", };
[550e819]84 static_assert(
85 sizeof(typeVariableNames)/sizeof(typeVariableNames[0]) == TypeDecl::NUMBER_OF_KINDS,
86 "Each type variable kind should have a demangle name prefix"
87 );
[04c77791]88 parsers.emplace_back(Encoding::typeVariables[k], [k, this](Type::Qualifiers tq) -> TypeInstType * {
89 PRINT( std::cerr << "type variable type: " << k << std::endl; )
[550e819]90 size_t N;
91 if (! extractNumber(N)) return nullptr;
92 return new TypeInstType(tq, toString(typeVariableNames[k], N), (TypeDecl::Kind)k != TypeDecl::Ftype);
[04c77791]93 });
94 }
[c20fafd]95 // everything else
96 parsers.emplace_back(Encoding::void_t, [this](Type::Qualifiers tq) { return parseVoid(tq); });
97 parsers.emplace_back(Encoding::function, [this](Type::Qualifiers tq) { return parseFunction(tq); });
98 parsers.emplace_back(Encoding::pointer, [this](Type::Qualifiers tq) { return parsePointer(tq); });
[2f9768f]99 parsers.emplace_back(Encoding::array, [this](Type::Qualifiers tq) { return parseArray(tq); });
[c20fafd]100 parsers.emplace_back(Encoding::tuple, [this](Type::Qualifiers tq) { return parseTuple(tq); });
101 parsers.emplace_back(Encoding::struct_t, [this](Type::Qualifiers tq) { return parseStruct(tq); });
[38587bc]102 parsers.emplace_back(Encoding::union_t, [this](Type::Qualifiers tq) { return parseUnion(tq); });
103 parsers.emplace_back(Encoding::enum_t, [this](Type::Qualifiers tq) { return parseEnum(tq); });
[efa8b6a]104 parsers.emplace_back(Encoding::type, [this](Type::Qualifiers tq) { return parseType(tq); });
[56b53b2]105 parsers.emplace_back(Encoding::zero, [](Type::Qualifiers tq) { return new ZeroType(tq); });
106 parsers.emplace_back(Encoding::one, [](Type::Qualifiers tq) { return new OneType(tq); });
[c20fafd]107 }
108
109 bool StringView::extractNumber(size_t & out) {
110 std::stringstream numss;
[efa8b6a]111 if (idx >= str.size()) return false;
[c20fafd]112 while (isdigit(str[idx])) {
113 numss << str[idx];
114 ++idx;
[efa8b6a]115 if (idx == str.size()) break;
[c20fafd]116 }
117 if (! (numss >> out)) return false;
[efa8b6a]118 PRINT( std::cerr << "extractNumber success: " << out << std::endl; )
[c20fafd]119 return true;
120 }
121
122 bool StringView::extractName(std::string & out) {
123 size_t len;
124 if (! extractNumber(len)) return false;
[efa8b6a]125 if (idx+len > str.size()) return false;
[c20fafd]126 out = str.substr(idx, len);
127 idx += len;
[efa8b6a]128 PRINT( std::cerr << "extractName success: " << out << std::endl; )
[c20fafd]129 return true;
130 }
131
132 bool StringView::isPrefix(const std::string & pref) {
[8abca06]133 // if ( pref.size() > str.size()-idx ) return false;
134 // auto its = std::mismatch( pref.begin(), pref.end(), std::next(str.begin(), idx) );
135 // if (its.first == pref.end()) {
136 // idx += pref.size();
137 // return true;
138 // }
139
140 // This update is untested because there are no tests for this code.
141 if ( ::isPrefix( str, pref, idx ) ) {
[c20fafd]142 idx += pref.size();
143 return true;
144 }
145 return false;
146 }
147
[d1e0979]148 // strips __NAME__cfa__TYPE_N, where N is [0-9]+: returns str is a match is found, returns empty string otherwise
[c20fafd]149 bool StringView::stripMangleName(std::string & name) {
150 PRINT( std::cerr << "====== " << str.size() << " " << str << std::endl; )
151 if (str.size() < 2+Encoding::manglePrefix.size()) return false; // +2 for at least _1 suffix
[8abca06]152 if ( ! isPrefix(Encoding::manglePrefix) || ! isdigit(str.back() ) ) return false;
[d1e0979]153
[c20fafd]154 // get name
155 if (! extractName(name)) return false;
[d1e0979]156
157 // find bounds for type
[c20fafd]158 PRINT( std::cerr << idx << " " << str.size() << std::endl; )
[d1e0979]159 PRINT( std::cerr << "[");
[c20fafd]160 while (isdigit(str.back())) {
[d1e0979]161 PRINT(std::cerr << ".");
[c20fafd]162 str.pop_back();
163 if (str.size() <= idx) return false;
[d1e0979]164 }
165 PRINT( std::cerr << "]" << std::endl );
[c20fafd]166 if (str.back() != '_') return false;
167 str.pop_back();
168 PRINT( std::cerr << str.size() << " " << name << " " << str.substr(idx) << std::endl; )
169 return str.size() > idx;
170 }
[d1e0979]171
[c20fafd]172 Type * StringView::parseFunction(Type::Qualifiers tq) {
173 PRINT( std::cerr << "function..." << std::endl; )
174 if (done()) return nullptr;
175 FunctionType * ftype = new FunctionType( tq, false );
[d7d63e5]176 std::unique_ptr<Type> manager(ftype);
[c20fafd]177 Type * retVal = parseType();
178 if (! retVal) return nullptr;
179 PRINT( std::cerr << "with return type: " << retVal << std::endl; )
180 ftype->returnVals.push_back(ObjectDecl::newObject("", retVal, nullptr));
181 if (done() || ! expect('_')) return nullptr;
182 while (! done()) {
183 PRINT( std::cerr << "got ch: " << cur() << std::endl; )
[d7d63e5]184 if (cur() == '_') return manager.release();
[c20fafd]185 Type * param = parseType();
186 if (! param) return nullptr;
187 PRINT( std::cerr << "with parameter : " << param << std::endl; )
188 ftype->parameters.push_back(ObjectDecl::newObject("", param, nullptr));
189 }
190 return nullptr;
[d1e0979]191 }
192
[c20fafd]193 Type * StringView::parseTuple(Type::Qualifiers tq) {
194 PRINT( std::cerr << "tuple..." << std::endl; )
195 std::list< Type * > types;
196 size_t ncomponents;
197 if (! extractNumber(ncomponents)) return nullptr;
198 for (size_t i = 0; i < ncomponents; ++i) {
[d7d63e5]199 // TODO: delete all on return
[c20fafd]200 if (done()) return nullptr;
201 PRINT( std::cerr << "got ch: " << cur() << std::endl; )
202 Type * t = parseType();
203 if (! t) return nullptr;
204 PRINT( std::cerr << "with type : " << t << std::endl; )
205 types.push_back(t);
206 }
207 return new TupleType( tq, types );
[d1e0979]208 }
209
[c20fafd]210 Type * StringView::parseVoid(Type::Qualifiers tq) {
211 return new VoidType( tq );
212 }
213
214 Type * StringView::parsePointer(Type::Qualifiers tq) {
215 PRINT( std::cerr << "pointer..." << std::endl; )
216 Type * t = parseType();
217 if (! t) return nullptr;
218 return new PointerType( tq, t );
219 }
220
[2f9768f]221 Type * StringView::parseArray(Type::Qualifiers tq) {
222 PRINT( std::cerr << "array..." << std::endl; )
223 size_t length;
224 if (! extractNumber(length)) return nullptr;
225 Type * t = parseType();
226 if (! t) return nullptr;
227 return new ArrayType( tq, t, new ConstantExpr( Constant::from_ulong(length) ), false, false );
228 }
229
[c20fafd]230 Type * StringView::parseStruct(Type::Qualifiers tq) {
231 PRINT( std::cerr << "struct..." << std::endl; )
232 std::string name;
233 if (! extractName(name)) return nullptr;
234 return new StructInstType(tq, name);
235 }
236
[38587bc]237 Type * StringView::parseUnion(Type::Qualifiers tq) {
238 PRINT( std::cerr << "union..." << std::endl; )
239 std::string name;
240 if (! extractName(name)) return nullptr;
241 return new UnionInstType(tq, name);
242 }
243
244 Type * StringView::parseEnum(Type::Qualifiers tq) {
245 PRINT( std::cerr << "enum..." << std::endl; )
246 std::string name;
247 if (! extractName(name)) return nullptr;
248 return new EnumInstType(tq, name);
249 }
250
[efa8b6a]251 Type * StringView::parseType(Type::Qualifiers tq) {
252 PRINT( std::cerr << "type..." << std::endl; )
253 std::string name;
254 if (! extractName(name)) return nullptr;
255 PRINT( std::cerr << "typename..." << name << std::endl; )
256 return new TypeInstType(tq, name, false);
257 }
258
[c20fafd]259 Type * StringView::parseType() {
260 if (done()) return nullptr;
[d1e0979]261
[04c77791]262 std::list<TypeDecl *> forall;
263 if (isPrefix(Encoding::forall)) {
264 PRINT( std::cerr << "polymorphic with..." << std::endl; )
265 size_t dcount, fcount, vcount, acount;
266 if (! extractNumber(dcount)) return nullptr;
267 PRINT( std::cerr << dcount << " dtypes" << std::endl; )
268 if (! expect('_')) return nullptr;
269 if (! extractNumber(fcount)) return nullptr;
270 PRINT( std::cerr << fcount << " ftypes" << std::endl; )
271 if (! expect('_')) return nullptr;
272 if (! extractNumber(vcount)) return nullptr;
273 PRINT( std::cerr << vcount << " ttypes" << std::endl; )
274 if (! expect('_')) return nullptr;
275 if (! extractNumber(acount)) return nullptr;
276 PRINT( std::cerr << acount << " assertions" << std::endl; )
277 if (! expect('_')) return nullptr;
[550e819]278 for (size_t i = 0; i < acount; ++i) {
279 // TODO: need to recursively parse assertions, but for now just return nullptr so that
280 // demangler does not crash if there are assertions
281 return nullptr;
282 }
[04c77791]283 if (! expect('_')) return nullptr;
284 }
285
[d1e0979]286 // qualifiers
287 Type::Qualifiers tq;
288 while (true) {
[c20fafd]289 auto qual = std::find_if(Encoding::qualifiers.begin(), Encoding::qualifiers.end(), [this](decltype(Encoding::qualifiers)::value_type val) {
290 return isPrefix(val.second);
[d1e0979]291 });
[c20fafd]292 if (qual == Encoding::qualifiers.end()) break;
[d1e0979]293 tq |= qual->first;
294 }
295
[c20fafd]296 // find the correct type parser and use it
297 auto iter = std::find_if(parsers.begin(), parsers.end(), [this](std::pair<std::string, parser> & p) {
298 return isPrefix(p.first);
[d1e0979]299 });
[c20fafd]300 assertf(iter != parsers.end(), "Unhandled type letter: %c at index: %zd", cur(), idx);
[04c77791]301 Type * ret = iter->second(tq);
302 if (! ret) return nullptr;
303 ret->forall = std::move(forall);
304 return ret;
[d1e0979]305 }
306
[c20fafd]307 bool StringView::parse(std::string & name, Type *& type) {
308 if (! stripMangleName(name)) return false;
309 PRINT( std::cerr << "stripped name: " << name << std::endl; )
310 Type * t = parseType();
311 if (! t) return false;
312 type = t;
313 return true;
[d1e0979]314 }
[f47d0ad]315
316 std::string demangle(const std::string & mangleName) {
317 SymTab::Mangler::StringView view(mangleName);
318 std::string name;
319 Type * type = nullptr;
320 if (! view.parse(name, type)) return mangleName;
[c649d2c]321 auto info = CodeGen::operatorLookupByOutput(name);
322 if (info) name = info->inputName;
[d7d63e5]323 std::unique_ptr<Type> manager(type);
[0589e83]324 return CodeGen::genType(type, name);
[f47d0ad]325 }
[d1e0979]326 } // namespace
327 } // namespace Mangler
328} // namespace SymTab
329
330extern "C" {
[90cac45]331 char * cforall_demangle(const char * mangleName, int option __attribute__((unused))) {
[f47d0ad]332 const std::string & demangleName = SymTab::Mangler::demangle(mangleName);
333 return strdup(demangleName.c_str());
334 }
[d1e0979]335}
336
337// Local Variables: //
338// tab-width: 4 //
339// mode: c++ //
340// compile-command: "make install" //
341// End: //
Note: See TracBrowser for help on using the repository browser.