diff --git a/toolchain/check/BUILD b/toolchain/check/BUILD index 3515cf5a2cf5..b4965e87d080 100644 --- a/toolchain/check/BUILD +++ b/toolchain/check/BUILD @@ -62,6 +62,7 @@ cc_library( "//toolchain/parse:tree", "//toolchain/parse:tree_node_location_translator", "//toolchain/sem_ir:builtin_kind", + "//toolchain/sem_ir:entry_point", "//toolchain/sem_ir:file", "//toolchain/sem_ir:node", "//toolchain/sem_ir:node_kind", diff --git a/toolchain/check/handle_function.cpp b/toolchain/check/handle_function.cpp index 061b24e47826..eaf2428c30f5 100644 --- a/toolchain/check/handle_function.cpp +++ b/toolchain/check/handle_function.cpp @@ -4,6 +4,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/convert.h" +#include "toolchain/sem_ir/entry_point.h" namespace Carbon::Check { @@ -59,6 +60,21 @@ static auto BuildFunctionDeclaration(Context& context) auto decl_id = context.AddNode( SemIR::Node::FunctionDeclaration::Make(fn_node, function_id)); context.declaration_name_stack().AddNameToLookup(name_context, decl_id); + + if (SemIR::IsEntryPoint(context.semantics_ir(), function_id)) { + // TODO: Update this once valid signatures for the entry point are decided. + if (!context.semantics_ir().GetNodeBlock(param_refs_id).empty() || + (return_slot_id.is_valid() && + return_type_id != + context.CanonicalizeType(SemIR::NodeId::BuiltinBoolType) && + return_type_id != context.CanonicalizeTupleType(fn_node, {}))) { + CARBON_DIAGNOSTIC(InvalidMainRunSignature, Error, + "Invalid signature for `Main.Run` function. Expected " + "`fn ()` or `fn () -> i32`."); + context.emitter().Emit(fn_node, InvalidMainRunSignature); + } + } + return {function_id, decl_id}; } diff --git a/toolchain/check/testdata/basics/fail_bad_run.carbon b/toolchain/check/testdata/basics/fail_bad_run.carbon new file mode 100644 index 000000000000..e0f0470845c7 --- /dev/null +++ b/toolchain/check/testdata/basics/fail_bad_run.carbon @@ -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_bad_run.carbon:[[@LINE+6]]:1: ERROR: Invalid signature for `Main.Run` function. Expected `fn ()` or `fn () -> i32`. +// CHECK:STDERR: fn Run() -> String {} +// CHECK:STDERR: ^ +// CHECK:STDERR: fail_bad_run.carbon:[[@LINE+3]]:21: ERROR: Missing `return` at end of function with declared return type. +// CHECK:STDERR: fn Run() -> String {} +// CHECK:STDERR: ^ +fn Run() -> String {} + +// CHECK:STDOUT: file "fail_bad_run.carbon" { +// CHECK:STDOUT: %Run = fn_decl @Run +// CHECK:STDOUT: %.loc13: type = tuple_type () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Run() -> %return: String { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: } diff --git a/toolchain/check/testdata/basics/fail_bad_run_2.carbon b/toolchain/check/testdata/basics/fail_bad_run_2.carbon new file mode 100644 index 000000000000..49dffd954408 --- /dev/null +++ b/toolchain/check/testdata/basics/fail_bad_run_2.carbon @@ -0,0 +1,19 @@ +// 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_bad_run_2.carbon:[[@LINE+3]]:1: ERROR: Invalid signature for `Main.Run` function. Expected `fn ()` or `fn () -> i32`. +// CHECK:STDERR: fn Run(n: i32) {} +// CHECK:STDERR: ^ +fn Run(n: i32) {} + +// CHECK:STDOUT: file "fail_bad_run_2.carbon" { +// CHECK:STDOUT: %Run = fn_decl @Run +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Run(%n: i32) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } diff --git a/toolchain/check/testdata/basics/run.carbon b/toolchain/check/testdata/basics/run.carbon new file mode 100644 index 000000000000..5680ceef7c29 --- /dev/null +++ b/toolchain/check/testdata/basics/run.carbon @@ -0,0 +1,16 @@ +// 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 Run() {} + +// CHECK:STDOUT: file "run.carbon" { +// CHECK:STDOUT: %Run = fn_decl @Run +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Run() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } diff --git a/toolchain/check/testdata/basics/run_i32.carbon b/toolchain/check/testdata/basics/run_i32.carbon new file mode 100644 index 000000000000..2222c8e186cb --- /dev/null +++ b/toolchain/check/testdata/basics/run_i32.carbon @@ -0,0 +1,17 @@ +// 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 Run() -> i32 { return 0; } + +// CHECK:STDOUT: file "run_i32.carbon" { +// CHECK:STDOUT: %Run = fn_decl @Run +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Run() -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc7: i32 = int_literal 0 +// CHECK:STDOUT: return %.loc7 +// CHECK:STDOUT: } diff --git a/toolchain/check/testdata/function/call/fail_param_type.carbon b/toolchain/check/testdata/function/call/fail_param_type.carbon index fd18560d02e9..70b9b86d6881 100644 --- a/toolchain/check/testdata/function/call/fail_param_type.carbon +++ b/toolchain/check/testdata/function/call/fail_param_type.carbon @@ -4,32 +4,32 @@ // // AUTOUPDATE -fn Run(a: i32) {} +fn G(a: i32) {} -fn Main() { - // CHECK:STDERR: fail_param_type.carbon:[[@LINE+6]]:6: ERROR: Cannot implicitly convert from `f64` to `i32`. - // CHECK:STDERR: Run(1.0); - // CHECK:STDERR: ^ +fn F() { + // CHECK:STDERR: fail_param_type.carbon:[[@LINE+6]]:4: ERROR: Cannot implicitly convert from `f64` to `i32`. + // CHECK:STDERR: G(1.0); + // CHECK:STDERR: ^ // CHECK:STDERR: fail_param_type.carbon:[[@LINE-6]]:1: Initializing parameter 1 of function declared here. - // CHECK:STDERR: fn Run(a: i32) {} + // CHECK:STDERR: fn G(a: i32) {} // CHECK:STDERR: ^ - Run(1.0); + G(1.0); } // CHECK:STDOUT: file "fail_param_type.carbon" { -// CHECK:STDOUT: %Run = fn_decl @Run -// CHECK:STDOUT: %Main = fn_decl @Main +// CHECK:STDOUT: %G = fn_decl @G +// CHECK:STDOUT: %F = fn_decl @F // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Run(%a: i32) { +// CHECK:STDOUT: fn @G(%a: i32) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Main() { +// CHECK:STDOUT: fn @F() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %Run.ref = name_reference_untyped "Run", package.%Run -// CHECK:STDOUT: %.loc16_7: f64 = real_literal 10e-1 -// CHECK:STDOUT: %.loc16_6: type = tuple_type () +// CHECK:STDOUT: %G.ref = name_reference_untyped "G", package.%G +// CHECK:STDOUT: %.loc16_5: f64 = real_literal 10e-1 +// CHECK:STDOUT: %.loc16_4: type = tuple_type () // CHECK:STDOUT: return // CHECK:STDOUT: } diff --git a/toolchain/diagnostics/diagnostic_kind.def b/toolchain/diagnostics/diagnostic_kind.def index f4281f27f7c0..12db6964e72f 100644 --- a/toolchain/diagnostics/diagnostic_kind.def +++ b/toolchain/diagnostics/diagnostic_kind.def @@ -125,6 +125,7 @@ CARBON_DIAGNOSTIC_KIND(RepeatedConst) CARBON_DIAGNOSTIC_KIND(InvalidArrayExpression) CARBON_DIAGNOSTIC_KIND(TypeNotIndexable) CARBON_DIAGNOSTIC_KIND(IndexOutOfBounds) +CARBON_DIAGNOSTIC_KIND(InvalidMainRunSignature) CARBON_DIAGNOSTIC_KIND(StructInitElementCountMismatch) CARBON_DIAGNOSTIC_KIND(StructInitFieldNameMismatch) CARBON_DIAGNOSTIC_KIND(TupleIndexIntegerLiteral) diff --git a/toolchain/lower/BUILD b/toolchain/lower/BUILD index eceeb5fa6990..3051a4a3574e 100644 --- a/toolchain/lower/BUILD +++ b/toolchain/lower/BUILD @@ -41,6 +41,7 @@ cc_library( deps = [ "//common:check", "//common:vlog", + "//toolchain/sem_ir:entry_point", "//toolchain/sem_ir:file", "//toolchain/sem_ir:node", "//toolchain/sem_ir:node_kind", diff --git a/toolchain/lower/file_context.cpp b/toolchain/lower/file_context.cpp index d511f1688668..77875fda4e44 100644 --- a/toolchain/lower/file_context.cpp +++ b/toolchain/lower/file_context.cpp @@ -8,6 +8,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Sequence.h" #include "toolchain/lower/function_context.h" +#include "toolchain/sem_ir/entry_point.h" #include "toolchain/sem_ir/file.h" #include "toolchain/sem_ir/node.h" #include "toolchain/sem_ir/node_kind.h" @@ -107,11 +108,20 @@ auto FileContext::BuildFunctionDeclaration(SemIR::FunctionId function_id) ? GetType(function.return_type_id) : llvm::Type::getVoidTy(llvm_context()); + std::string mangled_name; + if (SemIR::IsEntryPoint(semantics_ir(), function_id)) { + // TODO: Add an implicit `return 0` if `Run` doesn't return `i32`. + mangled_name = "main"; + } else { + // TODO: Decide on a name mangling scheme. + mangled_name = semantics_ir().GetString(function.name_id); + } + llvm::FunctionType* function_type = llvm::FunctionType::get(return_type, param_types, /*isVarArg=*/false); - auto* llvm_function = llvm::Function::Create( - function_type, llvm::Function::ExternalLinkage, - semantics_ir().GetString(function.name_id), llvm_module()); + auto* llvm_function = + llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, + mangled_name, llvm_module()); // Set up parameters and the return slot. for (auto [node_id, arg] : diff --git a/toolchain/lower/testdata/array/assign_return_value.carbon b/toolchain/lower/testdata/array/assign_return_value.carbon index 210bfa3a5188..f4c1573ff933 100644 --- a/toolchain/lower/testdata/array/assign_return_value.carbon +++ b/toolchain/lower/testdata/array/assign_return_value.carbon @@ -21,7 +21,7 @@ fn Run() { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: define void @Run() { +// CHECK:STDOUT: define void @main() { // CHECK:STDOUT: %t = alloca [2 x i32], align 4 // CHECK:STDOUT: %temp = alloca { i32, i32 }, align 8 // CHECK:STDOUT: call void @F(ptr %temp) diff --git a/toolchain/lower/testdata/array/base.carbon b/toolchain/lower/testdata/array/base.carbon index 048a867ad463..9cf5283263e2 100644 --- a/toolchain/lower/testdata/array/base.carbon +++ b/toolchain/lower/testdata/array/base.carbon @@ -15,7 +15,7 @@ fn Run() { // CHECK:STDOUT: ; ModuleID = 'base.carbon' // CHECK:STDOUT: source_filename = "base.carbon" // CHECK:STDOUT: -// CHECK:STDOUT: define void @Run() { +// CHECK:STDOUT: define void @main() { // CHECK:STDOUT: %a = alloca [1 x i32], align 4 // CHECK:STDOUT: %array.index = getelementptr inbounds [1 x i32], ptr %a, i32 0, i32 0 // CHECK:STDOUT: store i32 1, ptr %array.index, align 4 diff --git a/toolchain/lower/testdata/index/array_element_access.carbon b/toolchain/lower/testdata/index/array_element_access.carbon index b74f82a8152e..cdb586d20e61 100644 --- a/toolchain/lower/testdata/index/array_element_access.carbon +++ b/toolchain/lower/testdata/index/array_element_access.carbon @@ -33,7 +33,7 @@ fn Run() { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: define void @Run() { +// CHECK:STDOUT: define void @main() { // CHECK:STDOUT: %a = alloca [2 x i32], align 4 // CHECK:STDOUT: %temp = alloca { i32, i32 }, align 8 // CHECK:STDOUT: call void @A(ptr %temp) diff --git a/toolchain/lower/testdata/index/tuple_element_access.carbon b/toolchain/lower/testdata/index/tuple_element_access.carbon index ac0679a6e60a..c94468903d61 100644 --- a/toolchain/lower/testdata/index/tuple_element_access.carbon +++ b/toolchain/lower/testdata/index/tuple_element_access.carbon @@ -14,7 +14,7 @@ fn Run() -> i32 { // CHECK:STDOUT: ; ModuleID = 'tuple_element_access.carbon' // CHECK:STDOUT: source_filename = "tuple_element_access.carbon" // CHECK:STDOUT: -// CHECK:STDOUT: define i32 @Run() { +// CHECK:STDOUT: define i32 @main() { // CHECK:STDOUT: %a = alloca { i32, i32, i32 }, align 8 // CHECK:STDOUT: %tuple.elem = getelementptr inbounds { i32, i32, i32 }, ptr %a, i32 0, i32 0 // CHECK:STDOUT: store i32 0, ptr %tuple.elem, align 4 diff --git a/toolchain/lower/testdata/index/tuple_return_value_access.carbon b/toolchain/lower/testdata/index/tuple_return_value_access.carbon index d5647a38e3a0..05d681a7ca6e 100644 --- a/toolchain/lower/testdata/index/tuple_return_value_access.carbon +++ b/toolchain/lower/testdata/index/tuple_return_value_access.carbon @@ -21,7 +21,7 @@ fn Run() { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: define void @Run() { +// CHECK:STDOUT: define void @main() { // CHECK:STDOUT: %t = alloca i32, align 4 // CHECK:STDOUT: %temp = alloca { i32, i32 }, align 8 // CHECK:STDOUT: call void @F(ptr %temp) diff --git a/toolchain/lower/testdata/struct/empty.carbon b/toolchain/lower/testdata/struct/empty.carbon index 49a834f65b0a..d4d915086bae 100644 --- a/toolchain/lower/testdata/struct/empty.carbon +++ b/toolchain/lower/testdata/struct/empty.carbon @@ -13,7 +13,7 @@ fn Run() -> i32 { // CHECK:STDOUT: ; ModuleID = 'empty.carbon' // CHECK:STDOUT: source_filename = "empty.carbon" // CHECK:STDOUT: -// CHECK:STDOUT: define i32 @Run() { +// CHECK:STDOUT: define i32 @main() { // CHECK:STDOUT: %x = alloca {}, align 8 // CHECK:STDOUT: %y = alloca {}, align 8 // CHECK:STDOUT: ret i32 0 diff --git a/toolchain/lower/testdata/struct/member_access.carbon b/toolchain/lower/testdata/struct/member_access.carbon index 7bc855c6e488..7f56f5871db2 100644 --- a/toolchain/lower/testdata/struct/member_access.carbon +++ b/toolchain/lower/testdata/struct/member_access.carbon @@ -14,7 +14,7 @@ fn Run() -> i32 { // CHECK:STDOUT: ; ModuleID = 'member_access.carbon' // CHECK:STDOUT: source_filename = "member_access.carbon" // CHECK:STDOUT: -// CHECK:STDOUT: define i32 @Run() { +// CHECK:STDOUT: define i32 @main() { // CHECK:STDOUT: %x = alloca { double, i32 }, align 8 // CHECK:STDOUT: %a = getelementptr inbounds { double, i32 }, ptr %x, i32 0, i32 0 // CHECK:STDOUT: store double 0.000000e+00, ptr %a, align 8 diff --git a/toolchain/lower/testdata/struct/nested_struct.carbon b/toolchain/lower/testdata/struct/nested_struct.carbon index b90af4d6a692..de2b142545b5 100644 --- a/toolchain/lower/testdata/struct/nested_struct.carbon +++ b/toolchain/lower/testdata/struct/nested_struct.carbon @@ -12,6 +12,6 @@ fn Run() -> i32 { // CHECK:STDOUT: ; ModuleID = 'nested_struct.carbon' // CHECK:STDOUT: source_filename = "nested_struct.carbon" // CHECK:STDOUT: -// CHECK:STDOUT: define i32 @Run() { +// CHECK:STDOUT: define i32 @main() { // CHECK:STDOUT: ret i32 0 // CHECK:STDOUT: } diff --git a/toolchain/lower/testdata/struct/one_entry.carbon b/toolchain/lower/testdata/struct/one_entry.carbon index 99f74299ab56..219b36ea586c 100644 --- a/toolchain/lower/testdata/struct/one_entry.carbon +++ b/toolchain/lower/testdata/struct/one_entry.carbon @@ -13,7 +13,7 @@ fn Run() -> i32 { // CHECK:STDOUT: ; ModuleID = 'one_entry.carbon' // CHECK:STDOUT: source_filename = "one_entry.carbon" // CHECK:STDOUT: -// CHECK:STDOUT: define i32 @Run() { +// CHECK:STDOUT: define i32 @main() { // CHECK:STDOUT: %x = alloca { i32 }, align 8 // CHECK:STDOUT: store { i32 } { i32 4 }, ptr %x, align 4 // CHECK:STDOUT: %y = alloca { i32 }, align 8 diff --git a/toolchain/lower/testdata/struct/two_entries.carbon b/toolchain/lower/testdata/struct/two_entries.carbon index 80454d956db7..442ac23d4add 100644 --- a/toolchain/lower/testdata/struct/two_entries.carbon +++ b/toolchain/lower/testdata/struct/two_entries.carbon @@ -13,7 +13,7 @@ fn Run() -> i32 { // CHECK:STDOUT: ; ModuleID = 'two_entries.carbon' // CHECK:STDOUT: source_filename = "two_entries.carbon" // CHECK:STDOUT: -// CHECK:STDOUT: define i32 @Run() { +// CHECK:STDOUT: define i32 @main() { // CHECK:STDOUT: %x = alloca { i32, i32 }, align 8 // CHECK:STDOUT: %a = getelementptr inbounds { i32, i32 }, ptr %x, i32 0, i32 0 // CHECK:STDOUT: store i32 1, ptr %a, align 4 diff --git a/toolchain/lower/testdata/tuple/empty.carbon b/toolchain/lower/testdata/tuple/empty.carbon index b645586b98d7..64034cb6e8b0 100644 --- a/toolchain/lower/testdata/tuple/empty.carbon +++ b/toolchain/lower/testdata/tuple/empty.carbon @@ -13,7 +13,7 @@ fn Run() -> i32 { // CHECK:STDOUT: ; ModuleID = 'empty.carbon' // CHECK:STDOUT: source_filename = "empty.carbon" // CHECK:STDOUT: -// CHECK:STDOUT: define i32 @Run() { +// CHECK:STDOUT: define i32 @main() { // CHECK:STDOUT: %x = alloca {}, align 8 // CHECK:STDOUT: %y = alloca {}, align 8 // CHECK:STDOUT: ret i32 0 diff --git a/toolchain/lower/testdata/tuple/nested_tuple.carbon b/toolchain/lower/testdata/tuple/nested_tuple.carbon index 1e35308923aa..b0c0fde68f04 100644 --- a/toolchain/lower/testdata/tuple/nested_tuple.carbon +++ b/toolchain/lower/testdata/tuple/nested_tuple.carbon @@ -12,6 +12,6 @@ fn Run() -> i32 { // CHECK:STDOUT: ; ModuleID = 'nested_tuple.carbon' // CHECK:STDOUT: source_filename = "nested_tuple.carbon" // CHECK:STDOUT: -// CHECK:STDOUT: define i32 @Run() { +// CHECK:STDOUT: define i32 @main() { // CHECK:STDOUT: ret i32 0 // CHECK:STDOUT: } diff --git a/toolchain/lower/testdata/tuple/one_entry.carbon b/toolchain/lower/testdata/tuple/one_entry.carbon index a50218415d74..e2adaae1fa3b 100644 --- a/toolchain/lower/testdata/tuple/one_entry.carbon +++ b/toolchain/lower/testdata/tuple/one_entry.carbon @@ -13,7 +13,7 @@ fn Run() -> i32 { // CHECK:STDOUT: ; ModuleID = 'one_entry.carbon' // CHECK:STDOUT: source_filename = "one_entry.carbon" // CHECK:STDOUT: -// CHECK:STDOUT: define i32 @Run() { +// CHECK:STDOUT: define i32 @main() { // CHECK:STDOUT: %x = alloca { i32 }, align 8 // CHECK:STDOUT: store { i32 } { i32 1 }, ptr %x, align 4 // CHECK:STDOUT: %y = alloca { i32 }, align 8 diff --git a/toolchain/lower/testdata/tuple/two_entries.carbon b/toolchain/lower/testdata/tuple/two_entries.carbon index 93cf947b14ab..044b359acf3d 100644 --- a/toolchain/lower/testdata/tuple/two_entries.carbon +++ b/toolchain/lower/testdata/tuple/two_entries.carbon @@ -13,7 +13,7 @@ fn Run() -> i32 { // CHECK:STDOUT: ; ModuleID = 'two_entries.carbon' // CHECK:STDOUT: source_filename = "two_entries.carbon" // CHECK:STDOUT: -// CHECK:STDOUT: define i32 @Run() { +// CHECK:STDOUT: define i32 @main() { // CHECK:STDOUT: %x = alloca { i32, i32 }, align 8 // CHECK:STDOUT: %tuple.elem = getelementptr inbounds { i32, i32 }, ptr %x, i32 0, i32 0 // CHECK:STDOUT: store i32 12, ptr %tuple.elem, align 4 diff --git a/toolchain/lower/testdata/var/local.carbon b/toolchain/lower/testdata/var/local.carbon index bd7ad13283ea..d3c137eb6898 100644 --- a/toolchain/lower/testdata/var/local.carbon +++ b/toolchain/lower/testdata/var/local.carbon @@ -12,7 +12,7 @@ fn Run() -> i32 { // CHECK:STDOUT: ; ModuleID = 'local.carbon' // CHECK:STDOUT: source_filename = "local.carbon" // CHECK:STDOUT: -// CHECK:STDOUT: define i32 @Run() { +// CHECK:STDOUT: define i32 @main() { // CHECK:STDOUT: %x = alloca i32, align 4 // CHECK:STDOUT: store i32 1, ptr %x, align 4 // CHECK:STDOUT: %1 = load i32, ptr %x, align 4 diff --git a/toolchain/sem_ir/BUILD b/toolchain/sem_ir/BUILD index efb517b8ca6c..50e764d07abd 100644 --- a/toolchain/sem_ir/BUILD +++ b/toolchain/sem_ir/BUILD @@ -66,6 +66,16 @@ cc_library( ], ) +cc_library( + name = "entry_point", + srcs = ["entry_point.cpp"], + hdrs = ["entry_point.h"], + deps = [ + ":file", + "@llvm-project//llvm:Support", + ], +) + cc_test( name = "file_test", size = "small", diff --git a/toolchain/sem_ir/entry_point.cpp b/toolchain/sem_ir/entry_point.cpp new file mode 100644 index 000000000000..c78ac2610768 --- /dev/null +++ b/toolchain/sem_ir/entry_point.cpp @@ -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 + +#include "toolchain/sem_ir/entry_point.h" + +#include "llvm/ADT/StringRef.h" + +namespace Carbon::SemIR { + +static constexpr llvm::StringLiteral EntryPointFunction = "Run"; + +auto IsEntryPoint(const SemIR::File& file, SemIR::FunctionId function_id) + -> bool { + // TODO: Check if `file` is in the `Main` package. + auto& function = file.GetFunction(function_id); + // TODO: Check if `function` is in a namespace. + return function.name_id.is_valid() && + file.GetString(function.name_id) == EntryPointFunction; +} + +} // namespace Carbon::SemIR diff --git a/toolchain/sem_ir/entry_point.h b/toolchain/sem_ir/entry_point.h new file mode 100644 index 000000000000..033f44309652 --- /dev/null +++ b/toolchain/sem_ir/entry_point.h @@ -0,0 +1,19 @@ +// 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 + +#ifndef CARBON_TOOLCHAIN_SEM_IR_ENTRY_POINT_H_ +#define CARBON_TOOLCHAIN_SEM_IR_ENTRY_POINT_H_ + +#include "toolchain/sem_ir/file.h" + +namespace Carbon::SemIR { + +// Returns whether the specified function is the entry point function for the +// program, `Main.Run`. +auto IsEntryPoint(const SemIR::File& file, SemIR::FunctionId function_id) + -> bool; + +} // namespace Carbon::SemIR + +#endif // CARBON_TOOLCHAIN_SEM_IR_ENTRY_POINT_H_