// 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/lowering/lowering_context.h" namespace Carbon { auto LoweringHandleInvalid(LoweringContext& /*context*/, SemanticsNodeId /*node_id*/, SemanticsNode /*node*/) -> void { llvm_unreachable("never in actual IR"); } auto LoweringHandleCrossReference(LoweringContext& /*context*/, SemanticsNodeId /*node_id*/, SemanticsNode node) -> void { CARBON_FATAL() << "TODO: Add support: " << node; } auto LoweringHandleAssign(LoweringContext& context, SemanticsNodeId /*node_id*/, SemanticsNode node) -> void { auto [storage_id, value_id] = node.GetAsAssign(); if (value_id == SemanticsNodeId::BuiltinEmptyStruct || value_id == SemanticsNodeId::BuiltinEmptyTuple) { // Elide the 0-length store; these have no value assigned and it should have // no effect. return; } context.builder().CreateStore(context.GetLoweredNodeAsValue(value_id), context.GetLoweredNodeAsValue(storage_id)); } auto LoweringHandleBinaryOperatorAdd(LoweringContext& /*context*/, SemanticsNodeId /*node_id*/, SemanticsNode node) -> void { CARBON_FATAL() << "TODO: Add support: " << node; } auto LoweringHandleBindName(LoweringContext& /*context*/, SemanticsNodeId /*node_id*/, SemanticsNode /*node*/) -> void { // Probably need to do something here, but not necessary for now. } auto LoweringHandleBuiltin(LoweringContext& /*context*/, SemanticsNodeId /*node_id*/, SemanticsNode node) -> void { CARBON_FATAL() << "TODO: Add support: " << node; } auto LoweringHandleCall(LoweringContext& /*context*/, SemanticsNodeId /*node_id*/, SemanticsNode node) -> void { CARBON_FATAL() << "TODO: Add support: " << node; } auto LoweringHandleCodeBlock(LoweringContext& /*context*/, SemanticsNodeId /*node_id*/, SemanticsNode node) -> void { CARBON_FATAL() << "TODO: Add support: " << node; } auto LoweringHandleFunctionDeclaration(LoweringContext& context, SemanticsNodeId /*node_id*/, SemanticsNode node) -> void { auto [name_id, callable_id] = node.GetAsFunctionDeclaration(); auto callable = context.semantics_ir().GetCallable(callable_id); // TODO: Lower type information for the arguments prior to building args. auto param_refs = context.semantics_ir().GetNodeBlock(callable.param_refs_id); llvm::SmallVector args; args.resize_for_overwrite(param_refs.size()); for (int i = 0; i < static_cast(param_refs.size()); ++i) { args[i] = context.GetLoweredNodeAsType( context.semantics_ir().GetNode(param_refs[i]).type_id()); } llvm::Type* return_type = context.GetLoweredNodeAsType( callable.return_type_id.is_valid() ? callable.return_type_id : SemanticsNodeId::BuiltinEmptyTuple); llvm::FunctionType* function_type = llvm::FunctionType::get(return_type, args, /*isVarArg=*/false); auto* function = llvm::Function::Create( function_type, llvm::Function::ExternalLinkage, context.semantics_ir().GetString(name_id), context.llvm_module()); // Set parameter names. for (int i = 0; i < static_cast(param_refs.size()); ++i) { auto [param_name_id, _] = context.semantics_ir().GetNode(param_refs[i]).GetAsBindName(); function->getArg(i)->setName( context.semantics_ir().GetString(param_name_id)); } } auto LoweringHandleFunctionDefinition(LoweringContext& context, SemanticsNodeId /*node_id*/, SemanticsNode node) -> void { auto [declaration_id, body_block_id] = node.GetAsFunctionDefinition(); auto [name_id, callable_id] = context.semantics_ir().GetNode(declaration_id).GetAsFunctionDeclaration(); llvm::Function* function = context.llvm_module().getFunction( context.semantics_ir().GetString(name_id)); // Create a new basic block to start insertion into. llvm::BasicBlock* body = llvm::BasicBlock::Create(context.llvm_context(), "entry", function); context.todo_blocks().push_back({body, body_block_id}); } auto LoweringHandleIntegerLiteral(LoweringContext& context, SemanticsNodeId node_id, SemanticsNode node) -> void { SemanticsIntegerLiteralId int_id = node.GetAsIntegerLiteral(); llvm::APInt i = context.semantics_ir().GetIntegerLiteral(int_id); llvm::Value* v = context.builder().getInt32(i.getLimitedValue()); context.SetLoweredNodeAsValue(node_id, v); } auto LoweringHandleRealLiteral(LoweringContext& /*context*/, SemanticsNodeId /*node_id*/, SemanticsNode node) -> void { CARBON_FATAL() << "TODO: Add support: " << node; } auto LoweringHandleReturn(LoweringContext& context, SemanticsNodeId /*node_id*/, SemanticsNode /*node*/) -> void { context.builder().CreateRetVoid(); } auto LoweringHandleReturnExpression(LoweringContext& context, SemanticsNodeId /*node_id*/, SemanticsNode node) -> void { SemanticsNodeId expr_id = node.GetAsReturnExpression(); context.builder().CreateRet(context.GetLoweredNodeAsValue(expr_id)); } auto LoweringHandleStringLiteral(LoweringContext& /*context*/, SemanticsNodeId /*node_id*/, SemanticsNode node) -> void { CARBON_FATAL() << "TODO: Add support: " << node; } auto LoweringHandleStructMemberAccess(LoweringContext& context, SemanticsNodeId node_id, SemanticsNode node) -> void { auto [struct_id, member_index] = node.GetAsStructMemberAccess(); auto* struct_type = context.GetLoweredNodeAsType( context.semantics_ir().GetNode(struct_id).type_id()); auto* gep = context.builder().CreateStructGEP( struct_type, context.GetLoweredNodeAsValue(struct_id), member_index.index); context.SetLoweredNodeAsValue(node_id, gep); } auto LoweringHandleStructType(LoweringContext& /*context*/, SemanticsNodeId /*node_id*/, SemanticsNode /*node*/) -> void { // No action to take. } auto LoweringHandleStructTypeField(LoweringContext& /*context*/, SemanticsNodeId /*node_id*/, SemanticsNode node) -> void { CARBON_FATAL() << "TODO: Add support: " << node; } auto LoweringHandleStructValue(LoweringContext& context, SemanticsNodeId node_id, SemanticsNode node) -> void { auto* type = context.GetLoweredNodeAsType(node.type_id()); auto* alloca = context.builder().CreateAlloca(type); context.SetLoweredNodeAsValue(node_id, alloca); // TODO: Figure out changes to flow so that values are calculated for store. // Right now, the struct value IR is unevaluated. // auto refs = // context.semantics_ir().GetNodeBlock(node.GetAsStructValue().second); // for (int i = 0; i < static_cast(refs.size()); ++i) { // auto* gep = context.builder().CreateStructGEP(type, alloca, i); // context.builder().CreateStore(context.GetLoweredNodeAsValue(refs[i]), // gep); // } } auto LoweringHandleStubReference(LoweringContext& /*context*/, SemanticsNodeId /*node_id*/, SemanticsNode node) -> void { CARBON_FATAL() << "TODO: Add support: " << node; } auto LoweringHandleVarStorage(LoweringContext& context, SemanticsNodeId node_id, SemanticsNode node) -> void { // TODO: This doesn't handle globals. Also, LLVM requires globals to have a // name. Do we want to generate a name, which would need to be consistent // across translation units, or use the given name, which requires either // looking ahead for BindName or restructuring semantics, either of which // affects the destructuring due to the difference in storage? auto* alloca = context.builder().CreateAlloca( context.GetLoweredNodeAsType(node.type_id())); context.SetLoweredNodeAsValue(node_id, alloca); } } // namespace Carbon