Initial 'export name' handling. (#3949)

This adds a `BindExport` instruction in order to better track the
location of the `export` itself, but a `bind_name_id` is also added to
`ImportRef` so that we know quickly where to put it in name lookup.

Merging identical names is a TODO. I haven't quite decided how best to
achieve that, because I do think the BindExport should be what's
actually added to name lookup.

Also, I will probably add a mode to DeclNameStack that blocks
non-namespace scopes. This seems to already be an error, but the wrong
one (maybe due to lack of support for cross-file decl/def support).
This commit is contained in:
Jon Ross-Perkins
2024-05-17 18:05:52 +00:00
committed by GitHub
parent 122a361317
commit 40b2217421
22 changed files with 2135 additions and 234 deletions
@@ -0,0 +1,101 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// ============================================================================
// Setup files
// ============================================================================
// --- base.carbon
library "base" api;
fn F();
// --- export.carbon
library "export" api;
import library "base";
export F;
// ============================================================================
// Test files
// ============================================================================
// --- use_export.carbon
library "use_export" api;
import library "export";
var f: () = F();
// CHECK:STDOUT: --- base.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %F: type = fn_type @F [template]
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %struct: F = struct_value () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .F = %F.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %F.decl: F = fn_decl @F [template = constants.%struct] {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F();
// CHECK:STDOUT:
// CHECK:STDOUT: --- export.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %F: type = fn_type @F [template]
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %struct: F = struct_value () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .F = %import_ref
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref: F = import_ref ir1, inst+1, loaded [template = constants.%struct]
// CHECK:STDOUT: %F: F = bind_export F, %import_ref [template = constants.%struct]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F();
// CHECK:STDOUT:
// CHECK:STDOUT: --- use_export.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %F: type = fn_type @F [template]
// CHECK:STDOUT: %struct: F = struct_value () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .F = %import_ref
// CHECK:STDOUT: .f = %f
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref: F = import_ref ir1, inst+6, loaded [template = constants.%struct]
// CHECK:STDOUT: %.loc6_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc6_9.2: type = converted %.loc6_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %f.var: ref () = var f
// CHECK:STDOUT: %f: ref () = bind_name f, %f.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F();
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %F.ref: F = name_ref F, file.%import_ref [template = constants.%struct]
// CHECK:STDOUT: %F.call: init () = call %F.ref()
// CHECK:STDOUT: assign file.%f.var, %F.call
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT: