[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