diff --git a/lldb/source/Plugins/Language/Swift/SwiftLanguage.cpp b/lldb/source/Plugins/Language/Swift/SwiftLanguage.cpp
index 620b4033d4f97..721bb5a54d0d2 100644
--- a/lldb/source/Plugins/Language/Swift/SwiftLanguage.cpp
+++ b/lldb/source/Plugins/Language/Swift/SwiftLanguage.cpp
@@ -1719,17 +1719,10 @@ bool SwiftLanguage::GetFunctionDisplayName(
     return true;
   }
   case Language::FunctionNameRepresentation::eNameWithArgs: {
-    if (!sc.function)
-      return false;
-    if (sc.function->GetLanguage() != eLanguageTypeSwift)
-      return false;
-    std::string display_name = SwiftLanguageRuntime::DemangleSymbolAsString(
-        sc.function->GetMangled().GetMangledName().GetStringRef(),
-        SwiftLanguageRuntime::eSimplified, &sc, exe_ctx);
+    std::string display_name = GetFunctionName(sc, exe_ctx);
     if (display_name.empty())
       return false;
-    ExecutionContextScope *exe_scope =
-        exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL;
+    s << display_name;
     const InlineFunctionInfo *inline_info = NULL;
     VariableListSP variable_list_sp;
     bool get_function_vars = true;
@@ -1749,109 +1742,131 @@ bool SwiftLanguage::GetFunctionDisplayName(
           sc.function->GetBlock(true).GetBlockVariableList(true);
     }
 
-    if (inline_info) {
-      s << display_name;
-      s.PutCString(" [inlined] ");
-      display_name = inline_info->GetName().GetString();
-    }
-
     VariableList args;
     if (variable_list_sp)
       variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument,
                                                  args);
-    if (args.GetSize() == 0) {
-      s << display_name;
-      return true;
-    }
-    const char *cstr = display_name.data();
-    const char *open_paren = strchr(cstr, '(');
-    const char *close_paren = nullptr;
-    const char *generic = strchr(cstr, '<');
-    // If before the arguments list begins there is a template sign
-    // then scan to the end of the generic args before you try to find
-    // the arguments list.
-    if (generic && open_paren && generic < open_paren) {
-      int generic_depth = 1;
-      ++generic;
-      for (; *generic && generic_depth > 0; generic++) {
-        if (*generic == '<')
-          generic_depth++;
-        if (*generic == '>')
-          generic_depth--;
-      }
-      if (*generic)
-        open_paren = strchr(generic, '(');
-      else
-        open_paren = nullptr;
+
+    s << GetFunctionDisplayArgs(sc, args, exe_ctx);
+    return true;
     }
-    if (open_paren) {
-      close_paren = strchr(open_paren, ')');
     }
+    return false;
+}
 
-    if (open_paren)
-      s.Write(cstr, open_paren - cstr + 1);
-    else {
-      s << display_name;
-      s.PutChar('(');
+std::string SwiftLanguage::GetFunctionName(const SymbolContext &sc,
+                                           const ExecutionContext *exe_ctx) {
+  if (!sc.function)
+    return {};
+  if (sc.function->GetLanguage() != eLanguageTypeSwift)
+    return {};
+  std::string name = SwiftLanguageRuntime::DemangleSymbolAsString(
+      sc.function->GetMangled().GetMangledName().GetStringRef(),
+      SwiftLanguageRuntime::eSimplified, &sc, exe_ctx);
+  if (name.empty())
+    return {};
+  size_t open_paren = name.find('(');
+  size_t generic = name.find('<');
+  size_t name_end = std::min(open_paren, generic);
+  if (name_end == std::string::npos)
+    return name;
+  return name.substr(0, name_end);
+}
+
+std::string SwiftLanguage::GetFunctionDisplayArgs(
+    const SymbolContext &sc, VariableList &args,
+    const lldb_private::ExecutionContext *exe_ctx) {
+  ExecutionContextScope *exe_scope =
+      exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL;
+  std::string name = SwiftLanguageRuntime::DemangleSymbolAsString(
+      sc.function->GetMangled().GetMangledName().GetStringRef(),
+      SwiftLanguageRuntime::eSimplified, &sc, exe_ctx);
+  lldb_private::StreamString s;
+  const char *cstr = name.data();
+  const char *open_paren = strchr(cstr, '(');
+  const char *close_paren = nullptr;
+  const char *generic = strchr(cstr, '<');
+  // If before the arguments list begins there is a template sign
+  // then scan to the end of the generic args before you try to find
+  // the arguments list.
+  const char *generic_start = generic;
+  if (generic && open_paren && generic < open_paren) {
+    int generic_depth = 1;
+    ++generic;
+    for (; *generic && generic_depth > 0; generic++) {
+      if (*generic == '<')
+        generic_depth++;
+      if (*generic == '>')
+        generic_depth--;
     }
-    const size_t num_args = args.GetSize();
-    for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) {
-      std::string buffer;
-
-      VariableSP var_sp(args.GetVariableAtIndex(arg_idx));
-      ValueObjectSP var_value_sp(
-          ValueObjectVariable::Create(exe_scope, var_sp));
-      if (!var_sp || !var_value_sp || var_sp->IsArtificial())
-        continue;
-      StreamString ss;
-      const char *var_representation = nullptr;
-      const char *var_name = var_value_sp->GetName().GetCString();
-      if (var_value_sp->GetCompilerType().IsValid()) {
-        if (var_value_sp && exe_scope->CalculateTarget())
-          var_value_sp = var_value_sp->GetQualifiedRepresentationIfAvailable(
-              exe_scope->CalculateTarget()
-                  ->TargetProperties::GetPreferDynamicValue(),
-              exe_scope->CalculateTarget()
-                  ->TargetProperties::GetEnableSyntheticValue());
-        if (var_value_sp->GetCompilerType().IsAggregateType() &&
-            DataVisualization::ShouldPrintAsOneLiner(*var_value_sp.get())) {
-          static StringSummaryFormat format(TypeSummaryImpl::Flags()
-                                                .SetHideItemNames(false)
-                                                .SetShowMembersOneLiner(true),
-                                            "");
-          format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions());
-          var_representation = buffer.c_str();
-        } else
-          var_value_sp->DumpPrintableRepresentation(
-              ss,
-              ValueObject::ValueObjectRepresentationStyle::
-                  eValueObjectRepresentationStyleSummary,
-              eFormatDefault,
-              ValueObject::PrintableRepresentationSpecialCases::eAllow, false);
-      }
-      if (ss.GetData() && ss.GetSize())
-        var_representation = ss.GetData();
-      if (arg_idx > 0)
-        s.PutCString(", ");
-      if (var_value_sp->GetError().Success()) {
-        if (var_representation)
-          s.Printf("%s=%s", var_name, var_representation);
-        else
-          s.Printf("%s=%s at %s", var_name,
-                   var_value_sp->GetTypeName().GetCString(),
-                   var_value_sp->GetLocationAsCString());
+    if (*generic)
+      open_paren = strchr(generic, '(');
+    else
+      open_paren = nullptr;
+  }
+  if (open_paren) {
+    close_paren = strchr(open_paren, ')');
+  }
+
+  if (generic_start && generic_start < open_paren)
+    s.Write(generic_start, open_paren - generic_start);
+  s.PutChar('(');
+
+  const size_t num_args = args.GetSize();
+  for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) {
+    std::string buffer;
+
+    VariableSP var_sp(args.GetVariableAtIndex(arg_idx));
+    ValueObjectSP var_value_sp(ValueObjectVariable::Create(exe_scope, var_sp));
+    if (!var_sp || !var_value_sp || var_sp->IsArtificial())
+      continue;
+    StreamString ss;
+    const char *var_representation = nullptr;
+    const char *var_name = var_value_sp->GetName().GetCString();
+    if (var_value_sp->GetCompilerType().IsValid()) {
+      if (var_value_sp && exe_scope->CalculateTarget())
+        var_value_sp = var_value_sp->GetQualifiedRepresentationIfAvailable(
+            exe_scope->CalculateTarget()
+                ->TargetProperties::GetPreferDynamicValue(),
+            exe_scope->CalculateTarget()
+                ->TargetProperties::GetEnableSyntheticValue());
+      if (var_value_sp->GetCompilerType().IsAggregateType() &&
+          DataVisualization::ShouldPrintAsOneLiner(*var_value_sp.get())) {
+        static StringSummaryFormat format(TypeSummaryImpl::Flags()
+                                              .SetHideItemNames(false)
+                                              .SetShowMembersOneLiner(true),
+                                          "");
+        format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions());
+        var_representation = buffer.c_str();
       } else
-        s.Printf("%s=<unavailable>", var_name);
+        var_value_sp->DumpPrintableRepresentation(
+            ss,
+            ValueObject::ValueObjectRepresentationStyle::
+                eValueObjectRepresentationStyleSummary,
+            eFormatDefault,
+            ValueObject::PrintableRepresentationSpecialCases::eAllow, false);
     }
-
-    if (close_paren)
-      s.PutCString(close_paren);
-    else
-      s.PutChar(')');
-    } 
-    return true;
+    if (ss.GetData() && ss.GetSize())
+      var_representation = ss.GetData();
+    if (arg_idx > 0)
+      s.PutCString(", ");
+    if (var_value_sp->GetError().Success()) {
+      if (var_representation)
+        s.Printf("%s=%s", var_name, var_representation);
+      else
+        s.Printf("%s=%s at %s", var_name,
+                 var_value_sp->GetTypeName().GetCString(),
+                 var_value_sp->GetLocationAsCString());
+    } else
+      s.Printf("%s=<unavailable>", var_name);
   }
-  return false;
+
+  if (close_paren)
+    s.PutCString(close_paren);
+  else
+    s.PutChar(')');
+
+  return s.GetString().str();
 }
 
 void SwiftLanguage::GetExceptionResolverDescription(bool catch_on,
diff --git a/lldb/source/Plugins/Language/Swift/SwiftLanguage.h b/lldb/source/Plugins/Language/Swift/SwiftLanguage.h
index c93743f595661..353dab75284a8 100644
--- a/lldb/source/Plugins/Language/Swift/SwiftLanguage.h
+++ b/lldb/source/Plugins/Language/Swift/SwiftLanguage.h
@@ -69,6 +69,37 @@ class SwiftLanguage : public Language {
                               FunctionNameRepresentation representation,
                               Stream &s) override;
 
+  /// Returns the name of function up to the first generic or opening
+  /// parenthesis.
+  ///
+  /// The following function will have the name "foo":
+  /// \code{.swift}
+  /// func foo<T>(bar: T) {}
+  /// \endcode
+  ///
+  /// \param sc        The associated SymbolContext.
+  /// \param exe_ctx   The associated ExecutionContext.
+  /// \returns The name of a function as an std::string.
+  std::string GetFunctionName(const SymbolContext &sc,
+                              const ExecutionContext *exe_ctx);
+
+  /// Returns the arguments of a function call with its generics if any.
+  ///
+  /// Calling GetFunctionDisplayArgs on the following function call will return
+  /// "<Int>(bar=1)"
+  /// \code{.swift}
+  /// func foo<T>(bar: T) {}
+  /// foo(1)
+  /// \endcode
+  ///
+  /// \param sc        The associated SymbolContext.
+  /// \param args      The VariableList that are passed to the function.
+  /// \param exe_ctx   The associated ExecutionContext.
+  /// \returns The generics and arguments of a function call as an std::string.
+  std::string
+  GetFunctionDisplayArgs(const SymbolContext &sc, VariableList &args,
+                         const lldb_private::ExecutionContext *exe_ctx);
+
   void GetExceptionResolverDescription(bool catch_on, bool throw_on,
                                        Stream &s) override;
 
diff --git a/lldb/test/Shell/Swift/function-name-backtrace.test b/lldb/test/Shell/Swift/function-name-backtrace.test
new file mode 100644
index 0000000000000..2cac540b08156
--- /dev/null
+++ b/lldb/test/Shell/Swift/function-name-backtrace.test
@@ -0,0 +1,52 @@
+# XFAIL: target-windows
+
+# Test Swift function name printing in backtraces.
+
+# RUN: split-file %s %t
+# RUN: %target-swiftc -g %t/main.swift -o %t.out
+# RUN: %lldb -x -b -s %t/commands.input %t.out -o exit 2>&1 \
+# RUN:       | FileCheck %s
+
+#--- main.swift
+func foo() async -> Int {
+  return await try! bar(a: 1, b: 1)
+}
+
+var res = {
+    (index: Int) -> Int in
+    return index + 10
+}(1)
+
+fileprivate func bar(a: Int, b: Int) async throws -> Int {
+  var baz = Baz(baz: 1)
+  return res + a + b + Foo.foo_(a: baz)
+}
+
+struct Foo {
+  let foo: Int
+  static func foo_<T>(a: T) -> Int {
+    var a_ = a as! Baz
+    return a_.qux(a: 1)
+  }
+}
+
+struct Baz {
+  var baz: Int
+  mutating func qux<T>(a: T) -> Int {
+    baz += 1
+    return baz
+  }
+}
+
+await foo()
+
+#--- commands.input
+b qux
+
+run
+bt
+
+# CHECK: `Baz.qux<Int>(a=1)
+# CHECK: `static Foo.foo_<main.Baz>(a=(baz = 1))
+# CHECK: `bar(a=1, b=1)
+# CHECK: `foo()
\ No newline at end of file