diff --git a/proposals/0026-symbol-visibility.md b/proposals/0026-symbol-visibility.md
new file mode 100644
index 0000000..436460c
--- /dev/null
+++ b/proposals/0026-symbol-visibility.md
@@ -0,0 +1,93 @@
+# Global symbol visibility
+
+* Proposal: [0026](http://0026-filename.md)
+* Author(s): [Steven Perron](https://github.com/s-perron)
+* Status: **Design In Progress**
+
+## Introduction
+
+Section 3.6 of the
+[HLSL specification](https://microsoft.github.io/hlsl-specs/specs/hlsl.pdf)
+defined the possible linkages for names. This proposal updates how these
+linkages are represented in LLVM IR. The current implementation presents
+challenges for the SPIR-V backend due to inconsistencies with OpenCL. In HLSL, a
+name can have external linkage and program linkage, among others. If a name has
+external linkage, it is visible outside the translation unit, but not outside a
+linked program.
+A name with program linkage is visible outside a partially linked program.
+We propose
+that names with program linkage in HLSL should have external linkage and default
+visibility in LLVM IR, while names with external linkage in HLSL should have
+external linkage and hidden visibility in LLVM IR. They both have external
+linkage because they are visible outside the translation unit. Default
+visibility means the name is visible outside a shared library (program). Hidden
+visibility means the name is not visible outside the shared library (program).
+
+## Motivation
+
+The way HLSL linkage is represented in the current clang compiler is
+inconsistent with how OpenCL SPIRV represents equivalent concepts. Consider the
+following HLSL snippet:
+
+```
+void external_linkage() {}
+export void program_linkage() {}
+```
+
+In llvm-ir, these function will be represented as:
+
+```
+define void @external_linkage()() local_unnamed_addr [#0](#0) {
+ ret void
+}
+
+define void @program_linkage()() local_unnamed_addr [#1](#1) {
+ ret void
+}
+
+attributes #0 = { ... } # no hlsl.export
+attributes #1 = { ... "hlsl.export" ...}
+```
+
+In the DirectX backend, there is a pass that will “finalize” the linkage. It
+will change `@external_linkage’s` linkage to internal, and remove the
+`hlsl.export` attribute from `@program_linkage`.
+
+The SPIR-V backend emits the `Export` linkage attribute for every symbol with
+external linkage. For the example above, `external_linkage` would be decorated
+with the `Export` linkage attribute giving it the equivalent of program linkage.
+We cannot change this without modifying the behaviour for OpenCL. OpenCL
+generates functions that look exactly like `external_linkage` and they require
+the `Export` linkage attribute in the SPIR-V.
+
+To be consistent with OpenCL, we must represent function with program linkage
+the way we currently represent functions with `external_linkage`. Then we can
+distinguish functions with external linkage with some other attribute.
+
+## Proposed solution
+
+I propose mapping HLSL concepts found in section 3.6 of the HLSL specification
+as follows:
+
+ HLSL concept | LLVM-IR concept
+:------------------------------------|:-----------------
+ Translation unit | Translation unit
+ Program (partially or fully linked) | Shared library
+
+Then, we can map the HLSL linkages to LLVM IR as follows:
+
+| HLSL Linkage | LLVM-IR representation |
+|----------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| **Program linkage**:
Visible outside the program | **Linkage type: external**
**Visibility style: default**
These symbols are potentially visible outside the shared library. |
+| **External linkage**:
These symbols are visible outside the translation unit, but not outside the program. | **Linkage type: external**
**Visibility style: hidden**
These symbols are visible outside the translation unit and therefore participate in linking. However, the hidden visibility style means they are not visible outside the shared library. |
+| **Internal linkage**:
Visible anywhere in the translation unit, but not outside it. | **Linkage type: internal**
**Visibility style: default**
These symbols are accessible in the current translation unit but will be renamed to avoid collisions during linking. That is, they are not visible outside the translation unit. |
+
+See the LLVM language reference for definitions of the
+[linkage types](https://llvm.org/docs/LangRef.html) and
+[visibility styles](https://llvm.org/docs/LangRef.html).
+
+This provides a clean conceptual mapping from HLSL to LLVM IR and will be
+consistent with OpenCL’s implementation.
+
+Backends should assume they are generating HLSL programs. If any linking occurs,
+it happens before the backend.