lowering_handle.cpp 9.9 KB

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