lowering_handle.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "toolchain/lowering/lowering_context.h"
  5. namespace Carbon {
  6. auto LoweringHandleInvalid(LoweringContext& /*context*/,
  7. SemanticsNodeId /*node_id*/, SemanticsNode /*node*/)
  8. -> void {
  9. llvm_unreachable("never in actual IR");
  10. }
  11. auto LoweringHandleCrossReference(LoweringContext& /*context*/,
  12. SemanticsNodeId /*node_id*/,
  13. SemanticsNode node) -> void {
  14. CARBON_FATAL() << "TODO: Add support: " << node;
  15. }
  16. auto LoweringHandleAssign(LoweringContext& context, SemanticsNodeId /*node_id*/,
  17. SemanticsNode node) -> void {
  18. auto [storage_id, value_id] = node.GetAsAssign();
  19. if (value_id == SemanticsNodeId::BuiltinEmptyStruct ||
  20. value_id == SemanticsNodeId::BuiltinEmptyTuple) {
  21. // Elide the 0-length store; these have no value assigned and it should have
  22. // no effect.
  23. return;
  24. }
  25. context.builder().CreateStore(context.GetLoweredNodeAsValue(value_id),
  26. context.GetLoweredNodeAsValue(storage_id));
  27. }
  28. auto LoweringHandleBinaryOperatorAdd(LoweringContext& /*context*/,
  29. SemanticsNodeId /*node_id*/,
  30. SemanticsNode node) -> void {
  31. CARBON_FATAL() << "TODO: Add support: " << node;
  32. }
  33. auto LoweringHandleBindName(LoweringContext& /*context*/,
  34. SemanticsNodeId /*node_id*/, SemanticsNode /*node*/)
  35. -> void {
  36. // Probably need to do something here, but not necessary for now.
  37. }
  38. auto LoweringHandleBuiltin(LoweringContext& /*context*/,
  39. SemanticsNodeId /*node_id*/, SemanticsNode node)
  40. -> void {
  41. CARBON_FATAL() << "TODO: Add support: " << node;
  42. }
  43. auto LoweringHandleCall(LoweringContext& /*context*/,
  44. SemanticsNodeId /*node_id*/, SemanticsNode node)
  45. -> void {
  46. CARBON_FATAL() << "TODO: Add support: " << node;
  47. }
  48. auto LoweringHandleCodeBlock(LoweringContext& /*context*/,
  49. SemanticsNodeId /*node_id*/, SemanticsNode node)
  50. -> void {
  51. CARBON_FATAL() << "TODO: Add support: " << node;
  52. }
  53. auto LoweringHandleFunctionDeclaration(LoweringContext& context,
  54. SemanticsNodeId /*node_id*/,
  55. SemanticsNode node) -> void {
  56. auto [name_id, callable_id] = node.GetAsFunctionDeclaration();
  57. auto callable = context.semantics_ir().GetCallable(callable_id);
  58. // TODO: Lower type information for the arguments prior to building args.
  59. auto param_refs = context.semantics_ir().GetNodeBlock(callable.param_refs_id);
  60. llvm::SmallVector<llvm::Type*> args;
  61. args.resize_for_overwrite(param_refs.size());
  62. for (int i = 0; i < static_cast<int>(param_refs.size()); ++i) {
  63. args[i] = context.GetLoweredNodeAsType(
  64. context.semantics_ir().GetNode(param_refs[i]).type_id());
  65. }
  66. llvm::Type* return_type = context.GetLoweredNodeAsType(
  67. callable.return_type_id.is_valid() ? callable.return_type_id
  68. : SemanticsNodeId::BuiltinEmptyTuple);
  69. llvm::FunctionType* function_type =
  70. llvm::FunctionType::get(return_type, args, /*isVarArg=*/false);
  71. auto* function = llvm::Function::Create(
  72. function_type, llvm::Function::ExternalLinkage,
  73. context.semantics_ir().GetString(name_id), context.llvm_module());
  74. // Set parameter names.
  75. for (int i = 0; i < static_cast<int>(param_refs.size()); ++i) {
  76. auto [param_name_id, _] =
  77. context.semantics_ir().GetNode(param_refs[i]).GetAsBindName();
  78. function->getArg(i)->setName(
  79. context.semantics_ir().GetString(param_name_id));
  80. }
  81. }
  82. auto LoweringHandleFunctionDefinition(LoweringContext& context,
  83. SemanticsNodeId /*node_id*/,
  84. SemanticsNode node) -> void {
  85. auto [declaration_id, body_block_id] = node.GetAsFunctionDefinition();
  86. auto [name_id, callable_id] =
  87. context.semantics_ir().GetNode(declaration_id).GetAsFunctionDeclaration();
  88. llvm::Function* function = context.llvm_module().getFunction(
  89. context.semantics_ir().GetString(name_id));
  90. // Create a new basic block to start insertion into.
  91. llvm::BasicBlock* body =
  92. llvm::BasicBlock::Create(context.llvm_context(), "entry", function);
  93. context.todo_blocks().push_back({body, body_block_id});
  94. }
  95. auto LoweringHandleIntegerLiteral(LoweringContext& context,
  96. SemanticsNodeId node_id, SemanticsNode node)
  97. -> void {
  98. llvm::APInt i =
  99. context.semantics_ir().GetIntegerLiteral(node.GetAsIntegerLiteral());
  100. // TODO: This won't offer correct semantics, but seems close enough for now.
  101. llvm::Value* v =
  102. llvm::ConstantInt::get(context.builder().getInt32Ty(), i.getSExtValue());
  103. context.SetLoweredNodeAsValue(node_id, v);
  104. }
  105. auto LoweringHandleRealLiteral(LoweringContext& context,
  106. SemanticsNodeId node_id, SemanticsNode node)
  107. -> void {
  108. SemanticsRealLiteral real =
  109. context.semantics_ir().GetRealLiteral(node.GetAsRealLiteral());
  110. // TODO: This will probably have overflow issues, and should be fixed.
  111. double val =
  112. real.mantissa.getSExtValue() *
  113. std::pow((real.is_decimal ? 10 : 2), real.exponent.getSExtValue());
  114. llvm::APFloat llvm_val(val);
  115. context.SetLoweredNodeAsValue(
  116. node_id,
  117. llvm::ConstantFP::get(context.builder().getDoubleTy(), llvm_val));
  118. }
  119. auto LoweringHandleReturn(LoweringContext& context, SemanticsNodeId /*node_id*/,
  120. SemanticsNode /*node*/) -> void {
  121. context.builder().CreateRetVoid();
  122. }
  123. auto LoweringHandleReturnExpression(LoweringContext& context,
  124. SemanticsNodeId /*node_id*/,
  125. SemanticsNode node) -> void {
  126. SemanticsNodeId expr_id = node.GetAsReturnExpression();
  127. context.builder().CreateRet(context.GetLoweredNodeAsValue(expr_id));
  128. }
  129. auto LoweringHandleStringLiteral(LoweringContext& /*context*/,
  130. SemanticsNodeId /*node_id*/,
  131. SemanticsNode node) -> void {
  132. CARBON_FATAL() << "TODO: Add support: " << node;
  133. }
  134. auto LoweringHandleStructMemberAccess(LoweringContext& context,
  135. SemanticsNodeId node_id,
  136. SemanticsNode node) -> void {
  137. auto [struct_id, member_index] = node.GetAsStructMemberAccess();
  138. auto struct_type_id = context.semantics_ir().GetNode(struct_id).type_id();
  139. auto* llvm_type = context.GetLoweredNodeAsType(struct_type_id);
  140. // Get type information for member names.
  141. auto type_refs = context.semantics_ir().GetNodeBlock(
  142. context.semantics_ir().GetNode(struct_type_id).GetAsStructType());
  143. auto member_name = context.semantics_ir().GetString(
  144. context.semantics_ir()
  145. .GetNode(type_refs[member_index.index])
  146. .GetAsStructTypeField());
  147. auto* gep = context.builder().CreateStructGEP(
  148. llvm_type, context.GetLoweredNodeAsValue(struct_id), member_index.index,
  149. member_name);
  150. context.SetLoweredNodeAsValue(node_id, gep);
  151. }
  152. auto LoweringHandleStructType(LoweringContext& /*context*/,
  153. SemanticsNodeId /*node_id*/,
  154. SemanticsNode /*node*/) -> void {
  155. // No action to take.
  156. }
  157. auto LoweringHandleStructTypeField(LoweringContext& /*context*/,
  158. SemanticsNodeId /*node_id*/,
  159. SemanticsNode /*node*/) -> void {
  160. // No action to take.
  161. }
  162. auto LoweringHandleStructValue(LoweringContext& context,
  163. SemanticsNodeId node_id, SemanticsNode node)
  164. -> void {
  165. auto* llvm_type = context.GetLoweredNodeAsType(node.type_id());
  166. auto* alloca = context.builder().CreateAlloca(
  167. llvm_type, /*ArraySize=*/nullptr, "StructLiteralValue");
  168. context.SetLoweredNodeAsValue(node_id, alloca);
  169. auto refs = context.semantics_ir().GetNodeBlock(node.GetAsStructValue());
  170. // Get type information for member names.
  171. auto type_refs = context.semantics_ir().GetNodeBlock(
  172. context.semantics_ir().GetNode(node.type_id()).GetAsStructType());
  173. for (int i = 0; i < static_cast<int>(refs.size()); ++i) {
  174. auto member_name = context.semantics_ir().GetString(
  175. context.semantics_ir().GetNode(type_refs[i]).GetAsStructTypeField());
  176. auto* gep =
  177. context.builder().CreateStructGEP(llvm_type, alloca, i, member_name);
  178. context.builder().CreateStore(context.GetLoweredNodeAsValue(refs[i]), gep);
  179. }
  180. }
  181. auto LoweringHandleStubReference(LoweringContext& context,
  182. SemanticsNodeId node_id, SemanticsNode node)
  183. -> void {
  184. context.SetLoweredNodeAsValue(
  185. node_id, context.GetLoweredNodeAsValue(node.GetAsStubReference()));
  186. }
  187. auto LoweringHandleVarStorage(LoweringContext& context, SemanticsNodeId node_id,
  188. SemanticsNode node) -> void {
  189. // TODO: This should provide a name, not just `var`. Also, LLVM requires
  190. // globals to have a name. Do we want to generate a name, which would need to
  191. // be consistent across translation units, or use the given name, which
  192. // requires either looking ahead for BindName or restructuring semantics,
  193. // either of which affects the destructuring due to the difference in
  194. // storage?
  195. auto* alloca = context.builder().CreateAlloca(
  196. context.GetLoweredNodeAsType(node.type_id()), /*ArraySize=*/nullptr,
  197. "var");
  198. context.SetLoweredNodeAsValue(node_id, alloca);
  199. }
  200. } // namespace Carbon