DiggerLin created this revision.
DiggerLin added reviewers: hubert.reinterpretcast, jasonliu, sfertile, daltenty.
Herald added subscribers: cfe-commits, kbarton, hiraditya, nemanjai.
Herald added a project: clang.
DiggerLin edited the summary of this revision.
Herald added a subscriber: wuzish.
DiggerLin edited the summary of this revision.
DiggerLin edited the summary of this revision.

1. emit .extern  and .weak directive linkage
2. delete -u option for as in clang.

the c source code for test case  aix-extern-weak.ll as 
bash> cat test_extern_weak_all.c

extern int bar_extern(int* ip);
extern int bar_ref();
extern int b_e;

__attribute__ ((weak)) void foo_weak(){
}

__attribute__ ((weak)) void foo_ref_weak(){
}

extern __attribute__ ((weak)) void foo_ext_weak(void);

void foo(){ }

int (*bar_p)() = bar_ref;
void (*foo_weak_p)() = foo_ref_weak;
void (*foo_ext_weak_p)() = foo_ext_weak;

int __attribute__ ((weak)) b;
int main() {

  bar_extern(&b);
  foo();
  bar_p(&b_e);
  foo_weak_p();
  foo_ext_weak_p();
  foo_weak();

}


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D76932

Files:
  clang/lib/Driver/ToolChains/AIX.cpp
  llvm/include/llvm/CodeGen/AsmPrinter.h
  llvm/include/llvm/MC/MCAsmInfo.h
  llvm/include/llvm/MC/MCDirectives.h
  llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
  llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
  llvm/lib/MC/MCAsmInfoXCOFF.cpp
  llvm/lib/MC/MCAsmStreamer.cpp
  llvm/lib/MC/MCXCOFFStreamer.cpp
  llvm/lib/MC/XCOFFObjectWriter.cpp
  llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
  llvm/test/CodeGen/PowerPC/aix-extern-weak.ll
  llvm/test/CodeGen/PowerPC/aix-reference-func-addr-const.ll

Index: llvm/test/CodeGen/PowerPC/aix-reference-func-addr-const.ll
===================================================================
--- llvm/test/CodeGen/PowerPC/aix-reference-func-addr-const.ll
+++ llvm/test/CodeGen/PowerPC/aix-reference-func-addr-const.ll
@@ -15,6 +15,7 @@
 ;CHECK-NEXT:     .globl  foo_ptr
 ;CHECK-NEXT:     .align  2
 ;CHECK-NEXT:     foo_ptr:
+;CHECK-NEXT:     .extern foo[DS]
 ;CHECK-NEXT:     .long   foo[DS]
 ;CHECK-NEXT:     .globl  bar_ptr1
 ;CHECK-NEXT:     .align  2
@@ -25,6 +26,7 @@
 ;CHECK64-NEXT:         .globl  foo_ptr
 ;CHECK64-NEXT:         .align  3
 ;CHECK64-NEXT:    foo_ptr:
+;CHECK64-NEXT:          .extern foo[DS]
 ;CHECK64-NEXT:         .llong  foo[DS]
 ;CHECK64-NEXT:         .globl  bar_ptr1
 ;CHECK64-NEXT:         .align  3
Index: llvm/test/CodeGen/PowerPC/aix-extern-weak.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/PowerPC/aix-extern-weak.ll
@@ -0,0 +1,628 @@
+; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 \
+; RUN: -mattr=-altivec < %s | FileCheck --check-prefixes=COMMON,BIT32 %s
+
+; RUN: llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff -mcpu=pwr4 \
+; RUN: -mattr=-altivec < %s | FileCheck --check-prefixes=COMMON,BIT64 %s
+
+; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 \
+; RUN: -mattr=-altivec -filetype=obj -o %t.o < %s
+; RUN: llvm-readobj  --symbols %t.o | FileCheck --check-prefix=CHECKSYM %s
+
+@bar_p = global i32 (...)* @bar_ref, align 4
+@foo_weak_p = global void (...)* bitcast (void ()* @foo_ref_weak to void (...)*), align 4
+@foo_ext_weak_p = global void (...)* bitcast (void ()* @foo_ext_weak to void (...)*), align 4
+@b = weak global i32 0, align 4
+@b_e = external global i32, align 4
+
+define weak void @foo_weak() #0 {
+entry:
+  ret void
+}
+
+define weak void @foo_ref_weak() #0 {
+entry:
+  ret void
+}
+
+define void @foo() #0 {
+entry:
+  ret void
+}
+
+declare i32 @bar_ref(...) #1
+
+declare extern_weak void @foo_ext_weak() #1
+
+define i32 @main() #0 {
+entry:
+  %call = call i32 @bar_extern(i32* @b)
+  call void @foo()
+  %0 = load i32 (...)*, i32 (...)** @bar_p, align 4
+  %callee.knr.cast = bitcast i32 (...)* %0 to i32 (i32*)*
+  %call1 = call i32 %callee.knr.cast(i32* @b_e)
+  %1 = load void (...)*, void (...)** @foo_weak_p, align 4
+  %callee.knr.cast2 = bitcast void (...)* %1 to void ()*
+  call void %callee.knr.cast2()
+  %2 = load void (...)*, void (...)** @foo_ext_weak_p, align 4
+  %callee.knr.cast3 = bitcast void (...)* %2 to void ()*
+  call void %callee.knr.cast3()
+  call void @foo_weak()
+  ret i32 0
+}
+
+declare i32 @bar_extern(i32*) #1
+
+; COMMON:  	.weak	foo_weak[DS]            # -- Begin function foo_weak
+; COMMON-NEXT:	.weak	.foo_weak
+; COMMON-NEXT:	.align	4
+; COMMON-NEXT:	.csect foo_weak[DS]
+; BIT32-NEXT:	.long	.foo_weak               # @foo_weak
+; BIT32-NEXT:	.long	TOC[TC0]
+; BIT32-NEXT:	.long	0
+; BIT64-NEXT:	.llong	.foo_weak               # @foo_weak
+; BIT64-NEXT:	.llong	TOC[TC0]
+; BIT64-NEXT:	.llong	0
+; COMMON-NEXT:	.csect .text[PR]
+; COMMON-NEXT:.foo_weak:
+
+; COMMON:	        .weak	foo_ref_weak[DS]        # -- Begin function foo_ref_weak
+; COMMON-NEXT:	.weak	.foo_ref_weak
+; COMMON-NEXT:	.align	4
+; COMMON-NEXT:	.csect foo_ref_weak[DS]
+; BIT32-NEXT:	.long	.foo_ref_weak           # @foo_ref_weak
+; BIT32-NEXT:	.long	TOC[TC0]
+; BIT32-NEXT:	.long	0
+; BIT64-NEXT:	.llong	.foo_ref_weak           # @foo_ref_weak
+; BIT64-NEXT:	.llong	TOC[TC0]
+; BIT64-NEXT:	.llong	0
+; COMMON-NEXT:	.csect .text[PR]
+; COMMON-NEXT:.foo_ref_weak:
+
+; COMMON:  	.globl	foo[DS]                 # -- Begin function foo
+; COMMON-NEXT:	.globl	.foo
+; COMMON-NEXT:	.align	4
+; COMMON-NEXT:	.csect foo[DS]
+; BIT32-NEXT:	.long	.foo                    # @foo
+; BIT32-NEXT:	.long	TOC[TC0]
+; BIT32-NEXT:	.long	0
+; BIT64-NEXT:	.llong	.foo                    # @foo
+; BIT64-NEXT:	.llong	TOC[TC0]
+; BIT64-NEXT:	.llong	0
+; COMMON-NEXT:	.csect .text[PR]
+; COMMON-NEXT:.foo:
+
+; COMMON:  	.globl	main[DS]                # -- Begin function main
+; COMMON-NEXT:	.globl	.main
+; COMMON-NEXT:	.align	4
+; COMMON-NEXT:	.csect main[DS]
+; BIT32-NEXT:	.long	.main                   # @main
+; BIT32-NEXT:	.long	TOC[TC0]
+; BIT32-NEXT:	.long	0
+; BIT64-NEXT:	.llong	.main                   # @main
+; BIT64-NEXT:	.llong	TOC[TC0]
+; BIT64-NEXT:	.llong	0
+; COMMON-NEXT:	.csect .text[PR]
+; COMMON-NEXT:.main:
+
+; COMMON: 	.csect .data[RW]
+; COMMON-NEXT:	.globl	bar_p
+; BIT32-NEXT:	.align	2
+; BIT64-NEXT:	.align	3
+; COMMON-NEXT:bar_p:
+; COMMON-NEXT:	.extern	bar_ref[DS]
+; BIT32-NEXT:	.long	bar_ref[DS]
+; BIT64-NEXT:	.llong	bar_ref[DS]
+; COMMON-NEXT:	.globl	foo_weak_p
+; BIT32-NEXT:	.align	2
+; BIT64-NEXT:	.align	3
+; COMMON-NEXT:foo_weak_p:
+; BIT32-NEXT:	.long	foo_ref_weak[DS]
+; BIT64-NEXT:	.llong	foo_ref_weak[DS]
+; COMMON-NEXT:	.globl	foo_ext_weak_p
+; BIT32-NEXT:	.align	2
+; BIT64-NEXT:	.align	3
+; COMMON-NEXT:foo_ext_weak_p:
+; COMMON-NEXT:	.weak	foo_ext_weak[DS]
+; BIT32-NEXT:	.long	foo_ext_weak[DS]
+; BIT64-NEXT:	.llong	foo_ext_weak[DS]
+; COMMON-NEXT:	.weak	b
+; COMMON-NEXT:	.align	2
+; COMMON-NEXT:b:
+; COMMON-NEXT:	.long	0                       # 0x0
+; COMMON-NEXT:	.extern	b_e[UA]
+; COMMON-NEXT:	.extern	.bar_extern
+; COMMON-NEXT:	.toc
+; COMMON-NEXT:LC0:
+; COMMON-NEXT:	.tc b[TC],b
+; COMMON-NEXT:LC1:
+; COMMON-NEXT:	.tc bar_p[TC],bar_p
+; COMMON-NEXT:LC2:
+; COMMON-NEXT:	.tc b_e[TC],b_e[UA]
+; COMMON-NEXT:LC3:
+; COMMON-NEXT:	.tc foo_weak_p[TC],foo_weak_p
+; COMMON-NEXT:LC4:
+; COMMON-NEXT:	.tc foo_ext_weak_p[TC],foo_ext_weak_p
+
+
+; CHECKSYM: Symbols [
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index:]]
+; CHECKSYM-NEXT:     Name: .bar_extern
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0x0
+; CHECKSYM-NEXT:     Section: N_UNDEF
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_EXT (0x2)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+1]]
+; CHECKSYM-NEXT:       SectionLen: 0
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 0
+; CHECKSYM-NEXT:       SymbolType: XTY_ER (0x0)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_PR (0x0)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index+2]]
+; CHECKSYM-NEXT:     Name: bar_ref
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0x0
+; CHECKSYM-NEXT:     Section: N_UNDEF
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_EXT (0x2)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+3]]
+; CHECKSYM-NEXT:       SectionLen: 0
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 0
+; CHECKSYM-NEXT:       SymbolType: XTY_ER (0x0)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_DS (0xA)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index+4]]
+; CHECKSYM-NEXT:     Name: foo_ext_weak
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0x0
+; CHECKSYM-NEXT:     Section: N_UNDEF
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_WEAKEXT (0x6F)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+5]]
+; CHECKSYM-NEXT:       SectionLen: 0
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 0
+; CHECKSYM-NEXT:       SymbolType: XTY_ER (0x0)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_DS (0xA)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index+6]]
+; CHECKSYM-NEXT:     Name: b_e
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0x0
+; CHECKSYM-NEXT:     Section: N_UNDEF
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_EXT (0x2)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+7]]
+; CHECKSYM-NEXT:       SectionLen: 0
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 0
+; CHECKSYM-NEXT:       SymbolType: XTY_ER (0x0)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_UA (0x4)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index+8]]
+; CHECKSYM-NEXT:     Name: .text
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0x0
+; CHECKSYM-NEXT:     Section: .text
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_HIDEXT (0x6B)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+9]]
+; CHECKSYM-NEXT:       SectionLen: 224
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 4
+; CHECKSYM-NEXT:       SymbolType: XTY_SD (0x1)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_PR (0x0)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index+10]]
+; CHECKSYM-NEXT:     Name: .foo_weak
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0x0
+; CHECKSYM-NEXT:     Section: .text
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_WEAKEXT (0x6F)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+11]]
+; CHECKSYM-NEXT:       ContainingCsectSymbolIndex: 8
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 0
+; CHECKSYM-NEXT:       SymbolType: XTY_LD (0x2)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_PR (0x0)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index+12]]
+; CHECKSYM-NEXT:     Name: .foo_ref_weak
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0x10
+; CHECKSYM-NEXT:     Section: .text
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_WEAKEXT (0x6F)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+13]]
+; CHECKSYM-NEXT:       ContainingCsectSymbolIndex: 8
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 0
+; CHECKSYM-NEXT:       SymbolType: XTY_LD (0x2)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_PR (0x0)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index+14]]
+; CHECKSYM-NEXT:     Name: .foo
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0x20
+; CHECKSYM-NEXT:     Section: .text
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_EXT (0x2)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+15]]
+; CHECKSYM-NEXT:       ContainingCsectSymbolIndex: 8
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 0
+; CHECKSYM-NEXT:       SymbolType: XTY_LD (0x2)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_PR (0x0)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index+16]]
+; CHECKSYM-NEXT:     Name: .main
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0x30
+; CHECKSYM-NEXT:     Section: .text
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_EXT (0x2)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+17]]
+; CHECKSYM-NEXT:       ContainingCsectSymbolIndex: 8
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 0
+; CHECKSYM-NEXT:       SymbolType: XTY_LD (0x2)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_PR (0x0)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index+18]]
+; CHECKSYM-NEXT:     Name: .data
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0xE0
+; CHECKSYM-NEXT:     Section: .data
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_HIDEXT (0x6B)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+19]]
+; CHECKSYM-NEXT:       SectionLen: 16
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 2
+; CHECKSYM-NEXT:       SymbolType: XTY_SD (0x1)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_RW (0x5)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index+20]]
+; CHECKSYM-NEXT:     Name: bar_p
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0xE0
+; CHECKSYM-NEXT:     Section: .data
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_EXT (0x2)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+21]]
+; CHECKSYM-NEXT:       ContainingCsectSymbolIndex: 18
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 0
+; CHECKSYM-NEXT:       SymbolType: XTY_LD (0x2)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_RW (0x5)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index+22]]
+; CHECKSYM-NEXT:     Name: foo_weak_p
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0xE4
+; CHECKSYM-NEXT:     Section: .data
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_EXT (0x2)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+23]]
+; CHECKSYM-NEXT:       ContainingCsectSymbolIndex: 18
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 0
+; CHECKSYM-NEXT:       SymbolType: XTY_LD (0x2)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_RW (0x5)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index+24]]
+; CHECKSYM-NEXT:     Name: foo_ext_weak_p
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0xE8
+; CHECKSYM-NEXT:     Section: .data
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_EXT (0x2)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+25]]
+; CHECKSYM-NEXT:       ContainingCsectSymbolIndex: 18
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 0
+; CHECKSYM-NEXT:       SymbolType: XTY_LD (0x2)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_RW (0x5)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index+26]]
+; CHECKSYM-NEXT:     Name: b
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0xEC
+; CHECKSYM-NEXT:     Section: .data
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_WEAKEXT (0x6F)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+27]]
+; CHECKSYM-NEXT:       ContainingCsectSymbolIndex: 18
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 0
+; CHECKSYM-NEXT:       SymbolType: XTY_LD (0x2)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_RW (0x5)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index+28]]
+; CHECKSYM-NEXT:     Name: foo_weak
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0xF0
+; CHECKSYM-NEXT:     Section: .data
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_WEAKEXT (0x6F)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+29]]
+; CHECKSYM-NEXT:       SectionLen: 12
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 2
+; CHECKSYM-NEXT:       SymbolType: XTY_SD (0x1)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_DS (0xA)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index+30]]
+; CHECKSYM-NEXT:     Name: foo_ref_weak
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0xFC
+; CHECKSYM-NEXT:     Section: .data
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_WEAKEXT (0x6F)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+31]]
+; CHECKSYM-NEXT:       SectionLen: 12
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 2
+; CHECKSYM-NEXT:       SymbolType: XTY_SD (0x1)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_DS (0xA)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index+32]]
+; CHECKSYM-NEXT:     Name: foo
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0x108
+; CHECKSYM-NEXT:     Section: .data
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_EXT (0x2)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+33]]
+; CHECKSYM-NEXT:       SectionLen: 12
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 2
+; CHECKSYM-NEXT:       SymbolType: XTY_SD (0x1)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_DS (0xA)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index+34]]
+; CHECKSYM-NEXT:     Name: main
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0x114
+; CHECKSYM-NEXT:     Section: .data
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_EXT (0x2)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+35]]
+; CHECKSYM-NEXT:       SectionLen: 12
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 2
+; CHECKSYM-NEXT:       SymbolType: XTY_SD (0x1)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_DS (0xA)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index+36]]
+; CHECKSYM-NEXT:     Name: TOC
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0x120
+; CHECKSYM-NEXT:     Section: .data
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_HIDEXT (0x6B)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+37]]
+; CHECKSYM-NEXT:       SectionLen: 0
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 2
+; CHECKSYM-NEXT:       SymbolType: XTY_SD (0x1)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_TC0 (0xF)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index+38]]
+; CHECKSYM-NEXT:     Name: b
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0x120
+; CHECKSYM-NEXT:     Section: .data
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_HIDEXT (0x6B)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+39]]
+; CHECKSYM-NEXT:       SectionLen: 4
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 2
+; CHECKSYM-NEXT:       SymbolType: XTY_SD (0x1)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_TC (0x3)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index+40]]
+; CHECKSYM-NEXT:     Name: bar_p
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0x124
+; CHECKSYM-NEXT:     Section: .data
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_HIDEXT (0x6B)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+41]]
+; CHECKSYM-NEXT:       SectionLen: 4
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 2
+; CHECKSYM-NEXT:       SymbolType: XTY_SD (0x1)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_TC (0x3)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index+42]]
+; CHECKSYM-NEXT:     Name: b_e
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0x128
+; CHECKSYM-NEXT:     Section: .data
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_HIDEXT (0x6B)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+43]]
+; CHECKSYM-NEXT:       SectionLen: 4
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 2
+; CHECKSYM-NEXT:       SymbolType: XTY_SD (0x1)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_TC (0x3)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index+44]]
+; CHECKSYM-NEXT:     Name: foo_weak_p
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0x12C
+; CHECKSYM-NEXT:     Section: .data
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_HIDEXT (0x6B)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+45]]
+; CHECKSYM-NEXT:       SectionLen: 4
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 2
+; CHECKSYM-NEXT:       SymbolType: XTY_SD (0x1)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_TC (0x3)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT:   Symbol {
+; CHECKSYM-NEXT:     Index: [[#Index+46]]
+; CHECKSYM-NEXT:     Name: foo_ext_weak_p
+; CHECKSYM-NEXT:     Value (RelocatableAddress): 0x130
+; CHECKSYM-NEXT:     Section: .data
+; CHECKSYM-NEXT:     Type: 0x0
+; CHECKSYM-NEXT:     StorageClass: C_HIDEXT (0x6B)
+; CHECKSYM-NEXT:     NumberOfAuxEntries: 1
+; CHECKSYM-NEXT:     CSECT Auxiliary Entry {
+; CHECKSYM-NEXT:       Index: [[#Index+47]]
+; CHECKSYM-NEXT:       SectionLen: 4
+; CHECKSYM-NEXT:       ParameterHashIndex: 0x0
+; CHECKSYM-NEXT:       TypeChkSectNum: 0x0
+; CHECKSYM-NEXT:       SymbolAlignmentLog2: 2
+; CHECKSYM-NEXT:       SymbolType: XTY_SD (0x1)
+; CHECKSYM-NEXT:       StorageMappingClass: XMC_TC (0x3)
+; CHECKSYM-NEXT:       StabInfoIndex: 0x0
+; CHECKSYM-NEXT:       StabSectNum: 0x0
+; CHECKSYM-NEXT:     }
+; CHECKSYM-NEXT:   }
+; CHECKSYM-NEXT: ]
Index: llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
===================================================================
--- llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -168,6 +168,8 @@
   void emitFunctionDescriptor() override;
 
   void emitEndOfAsmFile(Module &) override;
+
+  void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const override;
 };
 
 } // end anonymous namespace
@@ -1539,6 +1541,21 @@
   }
 }
 
+void PPCAIXAsmPrinter::emitLinkage(const GlobalValue *GV,
+                                   MCSymbol *GVSym) const {
+  MCSymbolXCOFF *XCOFFSym = cast<MCSymbolXCOFF>(GVSym);
+
+  if (XCOFFSym->hasContainingCsect()) {
+    MCSymbolXCOFF *QualName =
+        XCOFFSym->getContainingCsect()->getQualNameSymbol();
+    if (GVSym->getName() == QualName->getUnqualifiedName() &&
+        XCOFFSym->getContainingCsect()->getMappingClass() != XCOFF::XMC_PR) {
+      GVSym = QualName;
+    }
+    AsmPrinter::emitLinkage(GV, GVSym);
+  }
+}
+
 void PPCAIXAsmPrinter::SetupMachineFunction(MachineFunction &MF) {
   // Setup CurrentFnDescSym and its containing csect.
   MCSectionXCOFF *FnDescSec =
@@ -1569,7 +1586,13 @@
           F->isDeclaration()
               ? getObjFileLowering().getSectionForExternalReference(F, TM)
               : getObjFileLowering().getSectionForFunctionDescriptor(F, TM));
-
+       if (F->isDeclaration()) {
+        MCSymbolXCOFF *FSym = cast<MCSymbolXCOFF>(getSymbol(F));
+        if (!FSym->hasContainingCsect()) {
+          FSym->setContainingCsect(Csect);
+          emitLinkage(F, Csect->getQualNameSymbol());
+        }
+       }
       return MCSymbolRefExpr::create(Csect->getQualNameSymbol(), OutContext);
   }
   return PPCAsmPrinter::lowerConstant(CV);
@@ -1609,8 +1632,10 @@
   GVSym->setContainingCsect(Csect);
 
   // External global variables are already handled.
-  if (GV->isDeclaration())
+  if (GV->isDeclaration()) {
+    emitLinkage(GV, GVSym);
     return;
+  }
 
   if (!GVKind.isGlobalWriteableData() && !GVKind.isReadOnly())
     report_fatal_error("Encountered a global variable kind that is "
Index: llvm/lib/MC/XCOFFObjectWriter.cpp
===================================================================
--- llvm/lib/MC/XCOFFObjectWriter.cpp
+++ llvm/lib/MC/XCOFFObjectWriter.cpp
@@ -347,7 +347,9 @@
       // Handle undefined symbol.
       UndefinedCsects.emplace_back(ContainingCsect);
       SectionMap[ContainingCsect] = &UndefinedCsects.back();
-    } else {
+      if (nameShouldBeInStringTable(ContainingCsect->getSectionName()))
+        Strings.add(ContainingCsect->getSectionName());
+    }
       // If the symbol is the csect itself, we don't need to put the symbol
       // into csect's Syms.
       if (XSym == ContainingCsect->getQualNameSymbol())
@@ -361,7 +363,6 @@
              "Expected containing csect to exist in map");
       // Lookup the containing csect and add the symbol to it.
       SectionMap[ContainingCsect]->Syms.emplace_back(XSym);
-    }
 
     // If the name does not fit in the storage provided in the symbol table
     // entry, add it to the string table.
Index: llvm/lib/MC/MCXCOFFStreamer.cpp
===================================================================
--- llvm/lib/MC/MCXCOFFStreamer.cpp
+++ llvm/lib/MC/MCXCOFFStreamer.cpp
@@ -35,6 +35,7 @@
 
   switch (Attribute) {
   case MCSA_Global:
+  case llvm::MCSA_Extern:
     Symbol->setStorageClass(XCOFF::C_EXT);
     Symbol->setExternal(true);
     break;
@@ -42,6 +43,10 @@
     Symbol->setStorageClass(XCOFF::C_HIDEXT);
     Symbol->setExternal(true);
     break;
+  case llvm::MCSA_Weak:
+    Symbol->setStorageClass(XCOFF::C_WEAKEXT);
+    Symbol->setExternal(true);
+    break;
   default:
     report_fatal_error("Not implemented yet.");
   }
Index: llvm/lib/MC/MCAsmStreamer.cpp
===================================================================
--- llvm/lib/MC/MCAsmStreamer.cpp
+++ llvm/lib/MC/MCAsmStreamer.cpp
@@ -675,6 +675,9 @@
     break;
   case MCSA_Protected:      OS << "\t.protected\t";       break;
   case MCSA_Reference:      OS << "\t.reference\t";       break;
+  case MCSA_Extern:
+    OS << "\t.extern\t";
+    break;
   case MCSA_Weak:           OS << MAI->getWeakDirective(); break;
   case MCSA_WeakDefinition:
     OS << "\t.weak_definition\t";
Index: llvm/lib/MC/MCAsmInfoXCOFF.cpp
===================================================================
--- llvm/lib/MC/MCAsmInfoXCOFF.cpp
+++ llvm/lib/MC/MCAsmInfoXCOFF.cpp
@@ -15,6 +15,7 @@
 MCAsmInfoXCOFF::MCAsmInfoXCOFF() {
   IsLittleEndian = false;
   HasDotTypeDotSizeDirective = false;
+  HasDotExternDirective = true;
   COMMDirectiveAlignmentIsInBytes = false;
   LCOMMDirectiveAlignmentType = LCOMM::Log2Alignment;
   UseDotAlignForAlignment = true;
Index: llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
===================================================================
--- llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -2011,6 +2011,7 @@
     return XCOFF::C_EXT;
   case GlobalValue::ExternalWeakLinkage:
   case GlobalValue::LinkOnceODRLinkage:
+  case GlobalValue::WeakAnyLinkage:
     return XCOFF::C_WEAKEXT;
   case GlobalValue::AppendingLinkage:
     report_fatal_error(
Index: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
===================================================================
--- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -424,8 +424,10 @@
     }
     return;
   case GlobalValue::ExternalLinkage:
-    // If external, declare as a global symbol: .globl _foo
-    OutStreamer->emitSymbolAttribute(GVSym, MCSA_Global);
+    if (MAI->hasDotExternDirective() && GV->isDeclaration())
+      OutStreamer->emitSymbolAttribute(GVSym, MCSA_Extern);
+    else
+      OutStreamer->emitSymbolAttribute(GVSym, MCSA_Global);
     return;
   case GlobalValue::PrivateLinkage:
     return;
@@ -433,9 +435,11 @@
     if (MAI->hasDotLGloblDirective())
       OutStreamer->emitSymbolAttribute(GVSym, MCSA_LGlobal);
     return;
+  case GlobalValue::ExternalWeakLinkage:
+    OutStreamer->emitSymbolAttribute(GVSym, MCSA_Weak);
+    return;
   case GlobalValue::AppendingLinkage:
   case GlobalValue::AvailableExternallyLinkage:
-  case GlobalValue::ExternalWeakLinkage:
     llvm_unreachable("Should never emit this");
   }
   llvm_unreachable("Unknown linkage type!");
@@ -1484,6 +1488,17 @@
     if (!F.isDeclarationForLinker())
       continue;
     GlobalValue::VisibilityTypes V = F.getVisibility();
+
+    if (MAI->hasDotExternDirective()) {
+      MCSymbol *Name = getSymbol(&F);
+      if (MAI->needsFunctionDescriptors()) {
+        // Get the function entry point symbol.
+        Name = OutContext.getOrCreateSymbol("." + Name->getName());
+      }
+      emitLinkage(&F, Name);
+      continue;
+    }
+
     if (V == GlobalValue::DefaultVisibility)
       continue;
 
Index: llvm/include/llvm/MC/MCDirectives.h
===================================================================
--- llvm/include/llvm/MC/MCDirectives.h
+++ llvm/include/llvm/MC/MCDirectives.h
@@ -29,6 +29,7 @@
   MCSA_ELF_TypeGnuUniqueObject, /// .type _foo, @gnu_unique_object
   MCSA_Global,              ///< .globl
   MCSA_LGlobal,             ///< .lglobl (XCOFF)
+  MCSA_Extern,              ///< .extern (XCOFF)
   MCSA_Hidden,              ///< .hidden (ELF)
   MCSA_IndirectSymbol,      ///< .indirect_symbol (MachO)
   MCSA_Internal,            ///< .internal (ELF)
Index: llvm/include/llvm/MC/MCAsmInfo.h
===================================================================
--- llvm/include/llvm/MC/MCAsmInfo.h
+++ llvm/include/llvm/MC/MCAsmInfo.h
@@ -307,6 +307,10 @@
   /// false.
   bool HasAltEntry = false;
 
+  /// True if this target supports the XCOFF .extern directive.  Defaults to
+  /// false.
+  bool HasDotExternDirective = false;
+
   /// Used to declare a global as being a weak symbol. Defaults to ".weak".
   const char *WeakDirective;
 
@@ -582,6 +586,7 @@
   bool hasIdentDirective() const { return HasIdentDirective; }
   bool hasNoDeadStrip() const { return HasNoDeadStrip; }
   bool hasAltEntry() const { return HasAltEntry; }
+  bool hasDotExternDirective() const { return HasDotExternDirective; }
   const char *getWeakDirective() const { return WeakDirective; }
   const char *getWeakRefDirective() const { return WeakRefDirective; }
   bool hasWeakDefDirective() const { return HasWeakDefDirective; }
Index: llvm/include/llvm/CodeGen/AsmPrinter.h
===================================================================
--- llvm/include/llvm/CodeGen/AsmPrinter.h
+++ llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -661,7 +661,7 @@
 
   /// This emits linkage information about \p GVSym based on \p GV, if this is
   /// supported by the target.
-  void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const;
+  virtual void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const;
 
   /// Return the alignment for the specified \p GV.
   static Align getGVAlignment(const GlobalValue *GV, const DataLayout &DL,
Index: clang/lib/Driver/ToolChains/AIX.cpp
===================================================================
--- clang/lib/Driver/ToolChains/AIX.cpp
+++ clang/lib/Driver/ToolChains/AIX.cpp
@@ -41,12 +41,6 @@
     CmdArgs.push_back("-a64");
   }
 
-  // Accept an undefined symbol as an extern so that an error message is not
-  // displayed. Otherwise, undefined symbols are flagged with error messages.
-  // FIXME: This should be removed when the assembly generation from the
-  // compiler is able to write externs properly.
-  CmdArgs.push_back("-u");
-
   // Accept any mixture of instructions.
   // On Power for AIX and Linux, this behaviour matches that of GCC for both the
   // user-provided assembler source case and the compiler-produced assembler
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to