mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Initial support for builtin functions. (#3803)
For now, a builtin function is defined by specifying a string literal initializer in a function declaration: ```carbon fn MyBuiltin(a: i32) -> i32 = "builtin.name"; ``` End-to-end support is included for a sample `"int.add"` builtin performing integer addition, covering constant evaluation and code generation. The implementation here needs substantial refactoring before we'll be ready to start adding more builtins. That refactoring work will be coming next. This change is aiming to checkpoint some incremental progress.
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
// 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
|
||||
|
||||
fn Add(a: i32, b: i32) -> i32 = "int.add";
|
||||
|
||||
var arr: [i32; Add(1, 2)];
|
||||
|
||||
// CHECK:STDOUT: --- call.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %.1: i32 = int_literal 1 [template]
|
||||
// CHECK:STDOUT: %.2: i32 = int_literal 2 [template]
|
||||
// CHECK:STDOUT: %.3: i32 = int_literal 3 [template]
|
||||
// CHECK:STDOUT: %.4: type = array_type %.3, i32 [template]
|
||||
// CHECK:STDOUT: %.5: type = ptr_type [i32; 3] [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Add = %Add
|
||||
// CHECK:STDOUT: .arr = %arr
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Add: <function> = fn_decl @Add [template] {
|
||||
// CHECK:STDOUT: %a.loc7_8.1: i32 = param a
|
||||
// CHECK:STDOUT: @Add.%a: i32 = bind_name a, %a.loc7_8.1
|
||||
// CHECK:STDOUT: %b.loc7_16.1: i32 = param b
|
||||
// CHECK:STDOUT: @Add.%b: i32 = bind_name b, %b.loc7_16.1
|
||||
// CHECK:STDOUT: %return.var: ref i32 = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Add.ref: <function> = name_ref Add, %Add [template = %Add]
|
||||
// CHECK:STDOUT: %.loc9_20: i32 = int_literal 1 [template = constants.%.1]
|
||||
// CHECK:STDOUT: %.loc9_23: i32 = int_literal 2 [template = constants.%.2]
|
||||
// CHECK:STDOUT: %.loc9_19: init i32 = call %Add.ref(%.loc9_20, %.loc9_23) [template = constants.%.3]
|
||||
// CHECK:STDOUT: %.loc9_25: type = array_type %.loc9_19, i32 [template = constants.%.4]
|
||||
// CHECK:STDOUT: %arr.var: ref [i32; 3] = var arr
|
||||
// CHECK:STDOUT: %arr: ref [i32; 3] = bind_name arr, %arr.var
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Add(%a: i32, %b: i32) -> i32 = "int.add";
|
||||
// CHECK:STDOUT:
|
||||
@@ -0,0 +1,172 @@
|
||||
// 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
|
||||
|
||||
// --- core.carbon
|
||||
|
||||
package Core api;
|
||||
|
||||
interface Add {
|
||||
fn Op[self: Self](other: Self) -> Self;
|
||||
}
|
||||
|
||||
// --- user.carbon
|
||||
|
||||
import Core;
|
||||
|
||||
// TODO: This should be in `Core`, but currently impl lookup only looks in the
|
||||
// current file.
|
||||
impl i32 as Core.Add {
|
||||
fn Op[self: i32](other: i32) -> i32 = "int.add";
|
||||
}
|
||||
|
||||
var arr: [i32; 1 + 2] = (3, 4, 3 + 4);
|
||||
|
||||
// CHECK:STDOUT: --- core.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %.1: type = interface_type @Add [template]
|
||||
// CHECK:STDOUT: %.2: type = assoc_entity_type @Add, <function> [template]
|
||||
// CHECK:STDOUT: %.3: <associated <function> in Add> = assoc_entity element0, @Add.%Op [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Add = %Add.decl
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Add.decl: type = interface_decl @Add [template = constants.%.1] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: interface @Add {
|
||||
// CHECK:STDOUT: %Self: Add = bind_symbolic_name Self [symbolic]
|
||||
// CHECK:STDOUT: %Op: <function> = fn_decl @Op [template] {
|
||||
// CHECK:STDOUT: %Self.ref.loc5_15: Add = name_ref Self, %Self [symbolic = %Self]
|
||||
// CHECK:STDOUT: %.loc5_15.1: type = facet_type_access %Self.ref.loc5_15 [symbolic = %Self]
|
||||
// CHECK:STDOUT: %.loc5_15.2: type = converted %Self.ref.loc5_15, %.loc5_15.1 [symbolic = %Self]
|
||||
// CHECK:STDOUT: %self.loc5_9.1: Self = param self
|
||||
// CHECK:STDOUT: %self.loc5_9.2: Self = bind_name self, %self.loc5_9.1
|
||||
// CHECK:STDOUT: %Self.ref.loc5_28: Add = name_ref Self, %Self [symbolic = %Self]
|
||||
// CHECK:STDOUT: %.loc5_28.1: type = facet_type_access %Self.ref.loc5_28 [symbolic = %Self]
|
||||
// CHECK:STDOUT: %.loc5_28.2: type = converted %Self.ref.loc5_28, %.loc5_28.1 [symbolic = %Self]
|
||||
// CHECK:STDOUT: %other.loc5_21.1: Self = param other
|
||||
// CHECK:STDOUT: %other.loc5_21.2: Self = bind_name other, %other.loc5_21.1
|
||||
// CHECK:STDOUT: %Self.ref.loc5_37: Add = name_ref Self, %Self [symbolic = %Self]
|
||||
// CHECK:STDOUT: %.loc5_37.1: type = facet_type_access %Self.ref.loc5_37 [symbolic = %Self]
|
||||
// CHECK:STDOUT: %.loc5_37.2: type = converted %Self.ref.loc5_37, %.loc5_37.1 [symbolic = %Self]
|
||||
// CHECK:STDOUT: %return.var: ref Self = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %.loc5_41: <associated <function> in Add> = assoc_entity element0, %Op [template = constants.%.3]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = %Self
|
||||
// CHECK:STDOUT: .Op = %.loc5_41
|
||||
// CHECK:STDOUT: witness = (%Op)
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Op[@Add.%self.loc5_9.2: Self](@Add.%other.loc5_21.2: Self) -> Self;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- user.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %.1: type = interface_type @Add [template]
|
||||
// CHECK:STDOUT: %.2: <witness> = interface_witness (@impl.%Op) [template]
|
||||
// CHECK:STDOUT: %.3: i32 = int_literal 1 [template]
|
||||
// CHECK:STDOUT: %.4: i32 = int_literal 2 [template]
|
||||
// CHECK:STDOUT: %.5: type = assoc_entity_type @Add, <function> [template]
|
||||
// CHECK:STDOUT: %.6: <associated <function> in Add> = assoc_entity element0, file.%import_ref.6 [template]
|
||||
// CHECK:STDOUT: %.7: <bound method> = bound_method %.3, @impl.%Op [template]
|
||||
// CHECK:STDOUT: %.8: i32 = int_literal 3 [template]
|
||||
// CHECK:STDOUT: %.9: type = array_type %.8, i32 [template]
|
||||
// CHECK:STDOUT: %.10: type = ptr_type [i32; 3] [template]
|
||||
// CHECK:STDOUT: %.11: i32 = int_literal 3 [template]
|
||||
// CHECK:STDOUT: %.12: i32 = int_literal 4 [template]
|
||||
// CHECK:STDOUT: %.13: <bound method> = bound_method %.11, @impl.%Op [template]
|
||||
// CHECK:STDOUT: %.14: i32 = int_literal 7 [template]
|
||||
// CHECK:STDOUT: %.15: type = tuple_type (i32, i32, i32) [template]
|
||||
// CHECK:STDOUT: %.16: i32 = int_literal 0 [template]
|
||||
// CHECK:STDOUT: %.17: i32 = int_literal 1 [template]
|
||||
// CHECK:STDOUT: %.18: i32 = int_literal 2 [template]
|
||||
// CHECK:STDOUT: %.19: [i32; 3] = tuple_value (%.11, %.12, %.14) [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .arr = %arr
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.1]
|
||||
// CHECK:STDOUT: %import_ref.2: <associated <function> in Add> = import_ref ir1, inst+20, used [template = constants.%.6]
|
||||
// CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+3, unused
|
||||
// CHECK:STDOUT: %import_ref.4: <function> = import_ref ir1, inst+18, used [template = imports.%Op]
|
||||
// CHECK:STDOUT: impl_decl @impl {
|
||||
// CHECK:STDOUT: %Core.ref: <namespace> = name_ref Core, %Core [template = %Core]
|
||||
// CHECK:STDOUT: %Add.decl: invalid = interface_decl @Add [template = constants.%.1] {}
|
||||
// CHECK:STDOUT: %Add.ref: type = name_ref Add, %import_ref.1 [template = constants.%.1]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %.loc10_16: i32 = int_literal 1 [template = constants.%.3]
|
||||
// CHECK:STDOUT: %.loc10_20: i32 = int_literal 2 [template = constants.%.4]
|
||||
// CHECK:STDOUT: %import_ref.5: type = import_ref ir1, inst+1, used [template = constants.%.1]
|
||||
// CHECK:STDOUT: %import_ref.6 = import_ref ir1, inst+18, unused
|
||||
// CHECK:STDOUT: %.1: <function> = interface_witness_access @impl.%.1, element0 [template = @impl.%Op]
|
||||
// CHECK:STDOUT: %.loc10_18.1: <bound method> = bound_method %.loc10_16, %.1 [template = constants.%.7]
|
||||
// CHECK:STDOUT: %.loc10_18.2: init i32 = call %.loc10_18.1(%.loc10_16, %.loc10_20) [template = constants.%.8]
|
||||
// CHECK:STDOUT: %.loc10_21: type = array_type %.loc10_18.2, i32 [template = constants.%.9]
|
||||
// CHECK:STDOUT: %arr.var: ref [i32; 3] = var arr
|
||||
// CHECK:STDOUT: %arr: ref [i32; 3] = bind_name arr, %arr.var
|
||||
// CHECK:STDOUT: %import_ref.7: type = import_ref ir1, inst+1, used [template = constants.%.1]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: interface @Add {
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Op = file.%import_ref.2
|
||||
// CHECK:STDOUT: .Self = file.%import_ref.3
|
||||
// CHECK:STDOUT: witness = (file.%import_ref.4)
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: impl @impl: i32 as Add {
|
||||
// CHECK:STDOUT: %Op: <function> = fn_decl @Op.1 [template] {
|
||||
// CHECK:STDOUT: %self.loc7_9.1: i32 = param self
|
||||
// CHECK:STDOUT: %self.loc7_9.2: i32 = bind_name self, %self.loc7_9.1
|
||||
// CHECK:STDOUT: %other.loc7_20.1: i32 = param other
|
||||
// CHECK:STDOUT: %other.loc7_20.2: i32 = bind_name other, %other.loc7_20.1
|
||||
// CHECK:STDOUT: %return.var: ref i32 = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %.1: <witness> = interface_witness (%Op) [template = constants.%.2]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Op = %Op
|
||||
// CHECK:STDOUT: witness = %.1
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Op.1[@impl.%self.loc7_9.2: i32](@impl.%other.loc7_20.2: i32) -> i32 = "int.add";
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Op.2[%self: Self](%other: Self) -> Self;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @__global_init() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %.loc10_26: i32 = int_literal 3 [template = constants.%.11]
|
||||
// CHECK:STDOUT: %.loc10_29: i32 = int_literal 4 [template = constants.%.12]
|
||||
// CHECK:STDOUT: %.loc10_32: i32 = int_literal 3 [template = constants.%.11]
|
||||
// CHECK:STDOUT: %.loc10_36: i32 = int_literal 4 [template = constants.%.12]
|
||||
// CHECK:STDOUT: %.1: <function> = interface_witness_access @impl.%.1, element0 [template = @impl.%Op]
|
||||
// CHECK:STDOUT: %.loc10_34.1: <bound method> = bound_method %.loc10_32, %.1 [template = constants.%.13]
|
||||
// CHECK:STDOUT: %.loc10_34.2: init i32 = call %.loc10_34.1(%.loc10_32, %.loc10_36) [template = constants.%.14]
|
||||
// CHECK:STDOUT: %.loc10_37.1: (i32, i32, i32) = tuple_literal (%.loc10_26, %.loc10_29, %.loc10_34.2)
|
||||
// CHECK:STDOUT: %.loc10_37.2: i32 = int_literal 0 [template = constants.%.16]
|
||||
// CHECK:STDOUT: %.loc10_37.3: ref i32 = array_index file.%arr.var, %.loc10_37.2
|
||||
// CHECK:STDOUT: %.loc10_37.4: init i32 = initialize_from %.loc10_26 to %.loc10_37.3 [template = constants.%.11]
|
||||
// CHECK:STDOUT: %.loc10_37.5: i32 = int_literal 1 [template = constants.%.17]
|
||||
// CHECK:STDOUT: %.loc10_37.6: ref i32 = array_index file.%arr.var, %.loc10_37.5
|
||||
// CHECK:STDOUT: %.loc10_37.7: init i32 = initialize_from %.loc10_29 to %.loc10_37.6 [template = constants.%.12]
|
||||
// CHECK:STDOUT: %.loc10_37.8: i32 = int_literal 2 [template = constants.%.18]
|
||||
// CHECK:STDOUT: %.loc10_37.9: ref i32 = array_index file.%arr.var, %.loc10_37.8
|
||||
// CHECK:STDOUT: %.loc10_37.10: init i32 = initialize_from %.loc10_34.2 to %.loc10_37.9 [template = constants.%.14]
|
||||
// CHECK:STDOUT: %.loc10_37.11: init [i32; 3] = array_init (%.loc10_37.4, %.loc10_37.7, %.loc10_37.10) to file.%arr.var [template = constants.%.19]
|
||||
// CHECK:STDOUT: %.loc10_37.12: init [i32; 3] = converted %.loc10_37.1, %.loc10_37.11 [template = constants.%.19]
|
||||
// CHECK:STDOUT: assign file.%arr.var, %.loc10_37.12
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -0,0 +1,25 @@
|
||||
// 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
|
||||
|
||||
fn Add(a: i32, b: i32) -> i32 = "int.add";
|
||||
|
||||
// CHECK:STDOUT: --- definition.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Add = %Add
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Add: <function> = fn_decl @Add [template] {
|
||||
// CHECK:STDOUT: %a.loc7_8.1: i32 = param a
|
||||
// CHECK:STDOUT: @Add.%a: i32 = bind_name a, %a.loc7_8.1
|
||||
// CHECK:STDOUT: %b.loc7_16.1: i32 = param b
|
||||
// CHECK:STDOUT: @Add.%b: i32 = bind_name b, %b.loc7_16.1
|
||||
// CHECK:STDOUT: %return.var: ref i32 = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Add(%a: i32, %b: i32) -> i32 = "int.add";
|
||||
// CHECK:STDOUT:
|
||||
@@ -0,0 +1,99 @@
|
||||
// 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
|
||||
|
||||
fn A(n: i32, m: i32) -> i32 = "int.add";
|
||||
// CHECK:STDERR: fail_redefined.carbon:[[@LINE+6]]:1: ERROR: Redefinition of function A.
|
||||
// CHECK:STDERR: fn A(n: i32, m: i32) -> i32 { return n; }
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_redefined.carbon:[[@LINE-4]]:1: Previously defined here.
|
||||
// CHECK:STDERR: fn A(n: i32, m: i32) -> i32 = "int.add";
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
fn A(n: i32, m: i32) -> i32 { return n; }
|
||||
|
||||
fn B(n: i32, m: i32) -> i32 { return n; }
|
||||
// CHECK:STDERR: fail_redefined.carbon:[[@LINE+6]]:1: ERROR: Redefinition of function B.
|
||||
// CHECK:STDERR: fn B(n: i32, m: i32) -> i32 = "int.add";
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_redefined.carbon:[[@LINE-4]]:1: Previously defined here.
|
||||
// CHECK:STDERR: fn B(n: i32, m: i32) -> i32 { return n; }
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
fn B(n: i32, m: i32) -> i32 = "int.add";
|
||||
|
||||
fn C(n: i32, m: i32) -> i32 = "int.add";
|
||||
// CHECK:STDERR: fail_redefined.carbon:[[@LINE+6]]:1: ERROR: Redefinition of function C.
|
||||
// CHECK:STDERR: fn C(n: i32, m: i32) -> i32 = "int.add";
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_redefined.carbon:[[@LINE-4]]:1: Previously defined here.
|
||||
// CHECK:STDERR: fn C(n: i32, m: i32) -> i32 = "int.add";
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
fn C(n: i32, m: i32) -> i32 = "int.add";
|
||||
|
||||
// CHECK:STDOUT: --- fail_redefined.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .A = %A.loc7
|
||||
// CHECK:STDOUT: .B = %B.loc16
|
||||
// CHECK:STDOUT: .C = %C.loc25
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %A.loc7: <function> = fn_decl @A [template] {
|
||||
// CHECK:STDOUT: %n.loc7_6.1: i32 = param n
|
||||
// CHECK:STDOUT: @A.%n: i32 = bind_name n, %n.loc7_6.1
|
||||
// CHECK:STDOUT: %m.loc7_14.1: i32 = param m
|
||||
// CHECK:STDOUT: @A.%m: i32 = bind_name m, %m.loc7_14.1
|
||||
// CHECK:STDOUT: %return.var.loc7: ref i32 = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %A.loc14: <function> = fn_decl @A [template] {
|
||||
// CHECK:STDOUT: %n.loc14_6.1: i32 = param n
|
||||
// CHECK:STDOUT: %n.loc14_6.2: i32 = bind_name n, %n.loc14_6.1
|
||||
// CHECK:STDOUT: %m.loc14_14.1: i32 = param m
|
||||
// CHECK:STDOUT: %m.loc14_14.2: i32 = bind_name m, %m.loc14_14.1
|
||||
// CHECK:STDOUT: %return.var.loc14: ref i32 = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %B.loc16: <function> = fn_decl @B [template] {
|
||||
// CHECK:STDOUT: %n.loc16_6.1: i32 = param n
|
||||
// CHECK:STDOUT: @B.%n: i32 = bind_name n, %n.loc16_6.1
|
||||
// CHECK:STDOUT: %m.loc16_14.1: i32 = param m
|
||||
// CHECK:STDOUT: @B.%m: i32 = bind_name m, %m.loc16_14.1
|
||||
// CHECK:STDOUT: %return.var.loc16: ref i32 = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %B.loc23: <function> = fn_decl @B [template] {
|
||||
// CHECK:STDOUT: %n.loc23_6.1: i32 = param n
|
||||
// CHECK:STDOUT: %n.loc23_6.2: i32 = bind_name n, %n.loc23_6.1
|
||||
// CHECK:STDOUT: %m.loc23_14.1: i32 = param m
|
||||
// CHECK:STDOUT: %m.loc23_14.2: i32 = bind_name m, %m.loc23_14.1
|
||||
// CHECK:STDOUT: %return.var.loc23: ref i32 = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %C.loc25: <function> = fn_decl @C [template] {
|
||||
// CHECK:STDOUT: %n.loc25_6.1: i32 = param n
|
||||
// CHECK:STDOUT: @C.%n: i32 = bind_name n, %n.loc25_6.1
|
||||
// CHECK:STDOUT: %m.loc25_14.1: i32 = param m
|
||||
// CHECK:STDOUT: @C.%m: i32 = bind_name m, %m.loc25_14.1
|
||||
// CHECK:STDOUT: %return.var.loc25: ref i32 = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %C.loc32: <function> = fn_decl @C [template] {
|
||||
// CHECK:STDOUT: %n.loc32_6.1: i32 = param n
|
||||
// CHECK:STDOUT: %n.loc32_6.2: i32 = bind_name n, %n.loc32_6.1
|
||||
// CHECK:STDOUT: %m.loc32_14.1: i32 = param m
|
||||
// CHECK:STDOUT: %m.loc32_14.2: i32 = bind_name m, %m.loc32_14.1
|
||||
// CHECK:STDOUT: %return.var.loc32: ref i32 = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @A(%n: i32, %m: i32) -> i32 = "int.add" {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %n.ref: i32 = name_ref n, file.%n.loc14_6.2
|
||||
// CHECK:STDOUT: return %n.ref
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @B(%n: i32, %m: i32) -> i32 = "int.add" {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %n.ref: i32 = name_ref n, %n
|
||||
// CHECK:STDOUT: return %n.ref
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @C(%n: i32, %m: i32) -> i32 = "int.add";
|
||||
// CHECK:STDOUT:
|
||||
@@ -0,0 +1,22 @@
|
||||
// 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
|
||||
|
||||
// CHECK:STDERR: fail_unknown.carbon:[[@LINE+3]]:23: ERROR: Unknown builtin function name "unknown.builtin.name".
|
||||
// CHECK:STDERR: fn UnknownBuiltin() = "unknown.builtin.name";
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~
|
||||
fn UnknownBuiltin() = "unknown.builtin.name";
|
||||
|
||||
// CHECK:STDOUT: --- fail_unknown.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .UnknownBuiltin = %UnknownBuiltin
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %UnknownBuiltin: <function> = fn_decl @UnknownBuiltin [template] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @UnknownBuiltin();
|
||||
// CHECK:STDOUT:
|
||||
@@ -0,0 +1,91 @@
|
||||
// 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
|
||||
|
||||
// --- core.carbon
|
||||
|
||||
package Core api;
|
||||
|
||||
fn Add(a: i32, b: i32) -> i32 = "int.add";
|
||||
|
||||
// --- use.carbon
|
||||
|
||||
import Core;
|
||||
|
||||
var arr: [i32; Core.Add(1, 2)] = (1, 2, 3);
|
||||
|
||||
// CHECK:STDOUT: --- core.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Add = %Add
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Add: <function> = fn_decl @Add [template] {
|
||||
// CHECK:STDOUT: %a.loc4_8.1: i32 = param a
|
||||
// CHECK:STDOUT: @Add.%a: i32 = bind_name a, %a.loc4_8.1
|
||||
// CHECK:STDOUT: %b.loc4_16.1: i32 = param b
|
||||
// CHECK:STDOUT: @Add.%b: i32 = bind_name b, %b.loc4_16.1
|
||||
// CHECK:STDOUT: %return.var: ref i32 = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Add(%a: i32, %b: i32) -> i32 = "int.add";
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- use.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %.1: i32 = int_literal 1 [template]
|
||||
// CHECK:STDOUT: %.2: i32 = int_literal 2 [template]
|
||||
// CHECK:STDOUT: %.3: i32 = int_literal 3 [template]
|
||||
// CHECK:STDOUT: %.4: type = array_type %.3, i32 [template]
|
||||
// CHECK:STDOUT: %.5: type = ptr_type [i32; 3] [template]
|
||||
// CHECK:STDOUT: %.6: i32 = int_literal 3 [template]
|
||||
// CHECK:STDOUT: %.7: type = tuple_type (i32, i32, i32) [template]
|
||||
// CHECK:STDOUT: %.8: i32 = int_literal 0 [template]
|
||||
// CHECK:STDOUT: %.9: i32 = int_literal 1 [template]
|
||||
// CHECK:STDOUT: %.10: i32 = int_literal 2 [template]
|
||||
// CHECK:STDOUT: %.11: [i32; 3] = tuple_value (%.1, %.2, %.6) [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .arr = %arr
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %Core.ref: <namespace> = name_ref Core, %Core [template = %Core]
|
||||
// CHECK:STDOUT: %import_ref: <function> = import_ref ir1, inst+6, used [template = imports.%Add]
|
||||
// CHECK:STDOUT: %Add.ref: <function> = name_ref Add, %import_ref [template = imports.%Add]
|
||||
// CHECK:STDOUT: %.loc4_25: i32 = int_literal 1 [template = constants.%.1]
|
||||
// CHECK:STDOUT: %.loc4_28: i32 = int_literal 2 [template = constants.%.2]
|
||||
// CHECK:STDOUT: %.loc4_24: init i32 = call %Add.ref(%.loc4_25, %.loc4_28) [template = constants.%.3]
|
||||
// CHECK:STDOUT: %.loc4_30: type = array_type %.loc4_24, i32 [template = constants.%.4]
|
||||
// CHECK:STDOUT: %arr.var: ref [i32; 3] = var arr
|
||||
// CHECK:STDOUT: %arr: ref [i32; 3] = bind_name arr, %arr.var
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Add(%a: i32, %b: i32) -> i32 = "int.add";
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @__global_init() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %.loc4_35: i32 = int_literal 1 [template = constants.%.1]
|
||||
// CHECK:STDOUT: %.loc4_38: i32 = int_literal 2 [template = constants.%.2]
|
||||
// CHECK:STDOUT: %.loc4_41: i32 = int_literal 3 [template = constants.%.6]
|
||||
// CHECK:STDOUT: %.loc4_42.1: (i32, i32, i32) = tuple_literal (%.loc4_35, %.loc4_38, %.loc4_41)
|
||||
// CHECK:STDOUT: %.loc4_42.2: i32 = int_literal 0 [template = constants.%.8]
|
||||
// CHECK:STDOUT: %.loc4_42.3: ref i32 = array_index file.%arr.var, %.loc4_42.2
|
||||
// CHECK:STDOUT: %.loc4_42.4: init i32 = initialize_from %.loc4_35 to %.loc4_42.3 [template = constants.%.1]
|
||||
// CHECK:STDOUT: %.loc4_42.5: i32 = int_literal 1 [template = constants.%.9]
|
||||
// CHECK:STDOUT: %.loc4_42.6: ref i32 = array_index file.%arr.var, %.loc4_42.5
|
||||
// CHECK:STDOUT: %.loc4_42.7: init i32 = initialize_from %.loc4_38 to %.loc4_42.6 [template = constants.%.2]
|
||||
// CHECK:STDOUT: %.loc4_42.8: i32 = int_literal 2 [template = constants.%.10]
|
||||
// CHECK:STDOUT: %.loc4_42.9: ref i32 = array_index file.%arr.var, %.loc4_42.8
|
||||
// CHECK:STDOUT: %.loc4_42.10: init i32 = initialize_from %.loc4_41 to %.loc4_42.9 [template = constants.%.6]
|
||||
// CHECK:STDOUT: %.loc4_42.11: init [i32; 3] = array_init (%.loc4_42.4, %.loc4_42.7, %.loc4_42.10) to file.%arr.var [template = constants.%.11]
|
||||
// CHECK:STDOUT: %.loc4_42.12: init [i32; 3] = converted %.loc4_42.1, %.loc4_42.11 [template = constants.%.11]
|
||||
// CHECK:STDOUT: assign file.%arr.var, %.loc4_42.12
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -0,0 +1,97 @@
|
||||
// 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
|
||||
|
||||
interface I {
|
||||
fn F[self: Self](other: Self) -> Self;
|
||||
}
|
||||
|
||||
impl i32 as I {
|
||||
fn F[self: i32](other: i32) -> i32 = "int.add";
|
||||
}
|
||||
|
||||
var arr: [i32; 1.(I.F)(2)];
|
||||
|
||||
// CHECK:STDOUT: --- method.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %.1: type = interface_type @I [template]
|
||||
// CHECK:STDOUT: %.2: type = assoc_entity_type @I, <function> [template]
|
||||
// CHECK:STDOUT: %.3: <associated <function> in I> = assoc_entity element0, @I.%F [template]
|
||||
// CHECK:STDOUT: %.4: <witness> = interface_witness (@impl.%F) [template]
|
||||
// CHECK:STDOUT: %.5: i32 = int_literal 1 [template]
|
||||
// CHECK:STDOUT: %.6: <bound method> = bound_method %.5, @impl.%F [template]
|
||||
// CHECK:STDOUT: %.7: i32 = int_literal 2 [template]
|
||||
// CHECK:STDOUT: %.8: i32 = int_literal 3 [template]
|
||||
// CHECK:STDOUT: %.9: type = array_type %.8, i32 [template]
|
||||
// CHECK:STDOUT: %.10: type = ptr_type [i32; 3] [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .I = %I.decl
|
||||
// CHECK:STDOUT: .arr = %arr
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %I.decl: type = interface_decl @I [template = constants.%.1] {}
|
||||
// CHECK:STDOUT: impl_decl @impl {
|
||||
// CHECK:STDOUT: %I.ref.loc11: type = name_ref I, %I.decl [template = constants.%.1]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %.loc15_16: i32 = int_literal 1 [template = constants.%.5]
|
||||
// CHECK:STDOUT: %I.ref.loc15: type = name_ref I, %I.decl [template = constants.%.1]
|
||||
// CHECK:STDOUT: %F.ref: <associated <function> in I> = name_ref F, @I.%.loc8_40 [template = constants.%.3]
|
||||
// CHECK:STDOUT: %.1: <function> = interface_witness_access @impl.%.1, element0 [template = @impl.%F]
|
||||
// CHECK:STDOUT: %.loc15_17: <bound method> = bound_method %.loc15_16, %.1 [template = constants.%.6]
|
||||
// CHECK:STDOUT: %.loc15_24: i32 = int_literal 2 [template = constants.%.7]
|
||||
// CHECK:STDOUT: %.loc15_23: init i32 = call %.loc15_17(%.loc15_16, %.loc15_24) [template = constants.%.8]
|
||||
// CHECK:STDOUT: %.loc15_26: type = array_type %.loc15_23, i32 [template = constants.%.9]
|
||||
// CHECK:STDOUT: %arr.var: ref [i32; 3] = var arr
|
||||
// CHECK:STDOUT: %arr: ref [i32; 3] = bind_name arr, %arr.var
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: interface @I {
|
||||
// CHECK:STDOUT: %Self: I = bind_symbolic_name Self [symbolic]
|
||||
// CHECK:STDOUT: %F: <function> = fn_decl @F.1 [template] {
|
||||
// CHECK:STDOUT: %Self.ref.loc8_14: I = name_ref Self, %Self [symbolic = %Self]
|
||||
// CHECK:STDOUT: %.loc8_14.1: type = facet_type_access %Self.ref.loc8_14 [symbolic = %Self]
|
||||
// CHECK:STDOUT: %.loc8_14.2: type = converted %Self.ref.loc8_14, %.loc8_14.1 [symbolic = %Self]
|
||||
// CHECK:STDOUT: %self.loc8_8.1: Self = param self
|
||||
// CHECK:STDOUT: %self.loc8_8.2: Self = bind_name self, %self.loc8_8.1
|
||||
// CHECK:STDOUT: %Self.ref.loc8_27: I = name_ref Self, %Self [symbolic = %Self]
|
||||
// CHECK:STDOUT: %.loc8_27.1: type = facet_type_access %Self.ref.loc8_27 [symbolic = %Self]
|
||||
// CHECK:STDOUT: %.loc8_27.2: type = converted %Self.ref.loc8_27, %.loc8_27.1 [symbolic = %Self]
|
||||
// CHECK:STDOUT: %other.loc8_20.1: Self = param other
|
||||
// CHECK:STDOUT: %other.loc8_20.2: Self = bind_name other, %other.loc8_20.1
|
||||
// CHECK:STDOUT: %Self.ref.loc8_36: I = name_ref Self, %Self [symbolic = %Self]
|
||||
// CHECK:STDOUT: %.loc8_36.1: type = facet_type_access %Self.ref.loc8_36 [symbolic = %Self]
|
||||
// CHECK:STDOUT: %.loc8_36.2: type = converted %Self.ref.loc8_36, %.loc8_36.1 [symbolic = %Self]
|
||||
// CHECK:STDOUT: %return.var: ref Self = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %.loc8_40: <associated <function> in I> = assoc_entity element0, %F [template = constants.%.3]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = %Self
|
||||
// CHECK:STDOUT: .F = %.loc8_40
|
||||
// CHECK:STDOUT: witness = (%F)
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: impl @impl: i32 as I {
|
||||
// CHECK:STDOUT: %F: <function> = fn_decl @F.2 [template] {
|
||||
// CHECK:STDOUT: %self.loc12_8.1: i32 = param self
|
||||
// CHECK:STDOUT: %self.loc12_8.2: i32 = bind_name self, %self.loc12_8.1
|
||||
// CHECK:STDOUT: %other.loc12_19.1: i32 = param other
|
||||
// CHECK:STDOUT: %other.loc12_19.2: i32 = bind_name other, %other.loc12_19.1
|
||||
// CHECK:STDOUT: %return.var: ref i32 = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %.1: <witness> = interface_witness (%F) [template = constants.%.4]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .F = %F
|
||||
// CHECK:STDOUT: witness = %.1
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.1[@I.%self.loc8_8.2: Self](@I.%other.loc8_20.2: Self) -> Self;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.2[@impl.%self.loc12_8.2: i32](@impl.%other.loc12_19.2: i32) -> i32 = "int.add";
|
||||
// CHECK:STDOUT:
|
||||
@@ -103,22 +103,22 @@ fn Main() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %Run0.ref.loc18: <function> = name_ref Run0, file.%Run0 [template = file.%Run0]
|
||||
// CHECK:STDOUT: %.loc18_8: i32 = int_literal 1 [template = constants.%.1]
|
||||
// CHECK:STDOUT: %.loc18_7: init () = call %Run0.ref.loc18(<invalid>)
|
||||
// CHECK:STDOUT: %.loc18_7: init () = call %Run0.ref.loc18(<invalid>) [template = <error>]
|
||||
// CHECK:STDOUT: %Run0.ref.loc25: <function> = name_ref Run0, file.%Run0 [template = file.%Run0]
|
||||
// CHECK:STDOUT: %.loc25_8: i32 = int_literal 0 [template = constants.%.3]
|
||||
// CHECK:STDOUT: %.loc25_11: i32 = int_literal 1 [template = constants.%.1]
|
||||
// CHECK:STDOUT: %.loc25_7: init () = call %Run0.ref.loc25(<invalid>)
|
||||
// CHECK:STDOUT: %.loc25_7: init () = call %Run0.ref.loc25(<invalid>) [template = <error>]
|
||||
// CHECK:STDOUT: %Run1.ref.loc33: <function> = name_ref Run1, file.%Run1 [template = file.%Run1]
|
||||
// CHECK:STDOUT: %.loc33: init () = call %Run1.ref.loc33(<invalid>)
|
||||
// CHECK:STDOUT: %.loc33: init () = call %Run1.ref.loc33(<invalid>) [template = <error>]
|
||||
// CHECK:STDOUT: %Run1.ref.loc40: <function> = name_ref Run1, file.%Run1 [template = file.%Run1]
|
||||
// CHECK:STDOUT: %.loc40_8: i32 = int_literal 0 [template = constants.%.3]
|
||||
// CHECK:STDOUT: %.loc40_11: i32 = int_literal 1 [template = constants.%.1]
|
||||
// CHECK:STDOUT: %.loc40_7: init () = call %Run1.ref.loc40(<invalid>)
|
||||
// CHECK:STDOUT: %.loc40_7: init () = call %Run1.ref.loc40(<invalid>) [template = <error>]
|
||||
// CHECK:STDOUT: %Run2.ref.loc48: <function> = name_ref Run2, file.%Run2 [template = file.%Run2]
|
||||
// CHECK:STDOUT: %.loc48: init () = call %Run2.ref.loc48(<invalid>)
|
||||
// CHECK:STDOUT: %.loc48: init () = call %Run2.ref.loc48(<invalid>) [template = <error>]
|
||||
// CHECK:STDOUT: %Run2.ref.loc55: <function> = name_ref Run2, file.%Run2 [template = file.%Run2]
|
||||
// CHECK:STDOUT: %.loc55_8: i32 = int_literal 0 [template = constants.%.3]
|
||||
// CHECK:STDOUT: %.loc55_7: init () = call %Run2.ref.loc55(<invalid>)
|
||||
// CHECK:STDOUT: %.loc55_7: init () = call %Run2.ref.loc55(<invalid>) [template = <error>]
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
|
||||
@@ -44,7 +44,7 @@ fn F() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %G.ref: <function> = name_ref G, file.%G [template = file.%G]
|
||||
// CHECK:STDOUT: %.loc16_5: f64 = real_literal 10e-1 [template = constants.%.1]
|
||||
// CHECK:STDOUT: %.loc16_4: init () = call %G.ref(<invalid>)
|
||||
// CHECK:STDOUT: %.loc16_4: init () = call %G.ref(<invalid>) [template = <error>]
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
|
||||
Reference in New Issue
Block a user