[llvm] r339471 - [MS Demangler] Support extern "C" functions.
Zachary Turner via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 10 14:09:05 PDT 2018
Author: zturner
Date: Fri Aug 10 14:09:05 2018
New Revision: 339471
URL: http://llvm.org/viewvc/llvm-project?rev=339471&view=rev
Log:
[MS Demangler] Support extern "C" functions.
There are two cases we need to support with extern "C"
functions. The first is the case of a '9' indicating that
the function has no prototype. This occurs when we mangle
a symbol inside of an extern "C" function, but not the
function itself.
The second case is when we have an overloaded extern "C"
functions. In this case we emit $$J0 to indicate this.
This patch adds support for both of these cases.
Modified:
llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp
llvm/trunk/test/Demangle/ms-mangle.test
Modified: llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp?rev=339471&r1=339470&r2=339471&view=diff
==============================================================================
--- llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp (original)
+++ llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp Fri Aug 10 14:09:05 2018
@@ -195,7 +195,7 @@ enum class PrimTy : uint8_t {
};
// Function classes
-enum FuncClass : uint8_t {
+enum FuncClass : uint16_t {
Public = 1 << 0,
Protected = 1 << 1,
Private = 1 << 2,
@@ -203,6 +203,8 @@ enum FuncClass : uint8_t {
Static = 1 << 4,
Virtual = 1 << 5,
Far = 1 << 6,
+ ExternC = 1 << 7,
+ NoPrototype = 1 << 8,
};
enum NameBackrefBehavior : uint8_t {
@@ -833,6 +835,9 @@ void FunctionType::outputPre(OutputStrea
if (FunctionClass & Static)
OS << "static ";
}
+ if (FunctionClass & ExternC) {
+ OS << "extern \"C\" ";
+ }
if (ReturnType) {
Type::outputPre(OS, *ReturnType, Resolver);
@@ -847,6 +852,10 @@ void FunctionType::outputPre(OutputStrea
}
void FunctionType::outputPost(OutputStream &OS, NameResolver &Resolver) {
+ // extern "C" functions don't have a prototype.
+ if (FunctionClass & NoPrototype)
+ return;
+
OS << "(";
outputParameterList(OS, Params, Resolver);
OS << ")";
@@ -1059,7 +1068,9 @@ Symbol *Demangler::parse(StringView &Man
if (Error)
return nullptr;
// Read a variable.
- if (startsWithDigit(MangledName)) {
+ if (startsWithDigit(MangledName) && !MangledName.startsWith('9')) {
+ // 9 is a special marker for an extern "C" function with
+ // no prototype.
S->Category = SymbolCategory::Variable;
S->SymbolType = demangleVariableEncoding(MangledName);
} else {
@@ -1517,47 +1528,53 @@ FuncClass Demangler::demangleFunctionCla
SwapAndRestore<StringView> RestoreOnError(MangledName, MangledName);
RestoreOnError.shouldRestore(false);
+ FuncClass TempFlags = FuncClass(0);
+ if (MangledName.consumeFront("$$J0"))
+ TempFlags = ExternC;
+
switch (MangledName.popFront()) {
+ case '9':
+ return FuncClass(TempFlags | ExternC | NoPrototype);
case 'A':
return Private;
case 'B':
- return FuncClass(Private | Far);
+ return FuncClass(TempFlags | Private | Far);
case 'C':
- return FuncClass(Private | Static);
+ return FuncClass(TempFlags | Private | Static);
case 'D':
- return FuncClass(Private | Static);
+ return FuncClass(TempFlags | Private | Static);
case 'E':
- return FuncClass(Private | Virtual);
+ return FuncClass(TempFlags | Private | Virtual);
case 'F':
- return FuncClass(Private | Virtual);
+ return FuncClass(TempFlags | Private | Virtual);
case 'I':
- return Protected;
+ return FuncClass(TempFlags | Protected);
case 'J':
- return FuncClass(Protected | Far);
+ return FuncClass(TempFlags | Protected | Far);
case 'K':
- return FuncClass(Protected | Static);
+ return FuncClass(TempFlags | Protected | Static);
case 'L':
- return FuncClass(Protected | Static | Far);
+ return FuncClass(TempFlags | Protected | Static | Far);
case 'M':
- return FuncClass(Protected | Virtual);
+ return FuncClass(TempFlags | Protected | Virtual);
case 'N':
- return FuncClass(Protected | Virtual | Far);
+ return FuncClass(TempFlags | Protected | Virtual | Far);
case 'Q':
- return Public;
+ return FuncClass(TempFlags | Public);
case 'R':
- return FuncClass(Public | Far);
+ return FuncClass(TempFlags | Public | Far);
case 'S':
- return FuncClass(Public | Static);
+ return FuncClass(TempFlags | Public | Static);
case 'T':
- return FuncClass(Public | Static | Far);
+ return FuncClass(TempFlags | Public | Static | Far);
case 'U':
- return FuncClass(Public | Virtual);
+ return FuncClass(TempFlags | Public | Virtual);
case 'V':
- return FuncClass(Public | Virtual | Far);
+ return FuncClass(TempFlags | Public | Virtual | Far);
case 'Y':
- return Global;
+ return FuncClass(TempFlags | Global);
case 'Z':
- return FuncClass(Global | Far);
+ return FuncClass(TempFlags | Global | Far);
}
Error = true;
@@ -1768,9 +1785,16 @@ FunctionType *Demangler::demangleFunctio
Type *Demangler::demangleFunctionEncoding(StringView &MangledName) {
FuncClass FC = demangleFunctionClass(MangledName);
-
- bool HasThisQuals = !(FC & (Global | Static));
- FunctionType *FTy = demangleFunctionType(MangledName, HasThisQuals, false);
+ FunctionType *FTy = nullptr;
+ if (FC & NoPrototype) {
+ // This is an extern "C" function whose full signature hasn't been mangled.
+ // This happens when we need to mangle a local symbol inside of an extern
+ // "C" function.
+ FTy = Arena.alloc<FunctionType>();
+ } else {
+ bool HasThisQuals = !(FC & (Global | Static));
+ FTy = demangleFunctionType(MangledName, HasThisQuals, false);
+ }
FTy->FunctionClass = FC;
return FTy;
Modified: llvm/trunk/test/Demangle/ms-mangle.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Demangle/ms-mangle.test?rev=339471&r1=339470&r2=339471&view=diff
==============================================================================
--- llvm/trunk/test/Demangle/ms-mangle.test (original)
+++ llvm/trunk/test/Demangle/ms-mangle.test Fri Aug 10 14:09:05 2018
@@ -268,12 +268,11 @@
?s6 at PR13182@@3PBQBDB
; CHECK: char const *const *PR13182::s6
-; FIXME: We don't properly support extern "C" functions yet.
-; ?local@?1??extern_c_func@@9 at 4HA
-; FIXME: int `extern_c_func'::`2'::local
+?local@?1??extern_c_func@@9 at 4HA
+; CHECK: int `extern "C" extern_c_func'::`2'::local
-; ?local@?1??extern_c_func@@9 at 4HA
-; FIXME: int `extern_c_func'::`2'::local
+?local@?1??extern_c_func@@9 at 4HA
+; CHECK: int `extern "C" extern_c_func'::`2'::local
?v@?1??f@@YAHXZ at 4U<unnamed-type-v>@?1??1 at YAHXZ@A
; CHECK: struct `int __cdecl f(void)'::`2'::<unnamed-type-v> `int __cdecl f(void)'::`2'::v
@@ -331,12 +330,11 @@
?vector_func@@YQXXZ
; CHECK: void __vectorcall vector_func(void)
-; FIXME: We don't support extern C funcs currently.
-; ??$fn_tmpl@$1?extern_c_func@@YAXXZ@@YAXXZ
-; FIXME: void __cdecl fn_tmpl<&void __cdecl extern_c_func(void)>(void)
+??$fn_tmpl@$1?extern_c_func@@YAXXZ@@YAXXZ
+; CHECK: void __cdecl fn_tmpl<&void __cdecl extern_c_func(void)>(void)
-; ?overloaded_fn@@$$J0YAXXZ
-; FIXME-EXTERNC: extern \"C\" void __cdecl overloaded_fn(void)
+?overloaded_fn@@$$J0YAXXZ
+; CHECK: extern "C" void __cdecl overloaded_fn(void)
?f at UnnamedType@@YAXQAPAU<unnamed-type-T1>@S at 1@@Z
; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::S::<unnamed-type-T1> **const)
More information about the llvm-commits
mailing list