lowering_handle.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  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_function_context.h"
  5. namespace Carbon {
  6. auto LoweringHandleInvalid(LoweringFunctionContext& /*context*/,
  7. SemanticsNodeId /*node_id*/, SemanticsNode /*node*/)
  8. -> void {
  9. llvm_unreachable("never in actual IR");
  10. }
  11. auto LoweringHandleCrossReference(LoweringFunctionContext& /*context*/,
  12. SemanticsNodeId /*node_id*/,
  13. SemanticsNode node) -> void {
  14. CARBON_FATAL() << "TODO: Add support: " << node;
  15. }
  16. auto LoweringHandleAssign(LoweringFunctionContext& context,
  17. SemanticsNodeId /*node_id*/, SemanticsNode node)
  18. -> void {
  19. auto [storage_id, value_id] = node.GetAsAssign();
  20. context.builder().CreateStore(context.GetLocalLoaded(value_id),
  21. context.GetLocal(storage_id));
  22. }
  23. auto LoweringHandleBinaryOperatorAdd(LoweringFunctionContext& /*context*/,
  24. SemanticsNodeId /*node_id*/,
  25. SemanticsNode node) -> void {
  26. CARBON_FATAL() << "TODO: Add support: " << node;
  27. }
  28. auto LoweringHandleBindName(LoweringFunctionContext& /*context*/,
  29. SemanticsNodeId /*node_id*/, SemanticsNode /*node*/)
  30. -> void {
  31. // Probably need to do something here, but not necessary for now.
  32. }
  33. auto LoweringHandleBlockArg(LoweringFunctionContext& context,
  34. SemanticsNodeId node_id, SemanticsNode node)
  35. -> void {
  36. SemanticsNodeBlockId block_id = node.GetAsBlockArg();
  37. context.SetLocal(node_id, context.GetBlockArg(block_id, node.type_id()));
  38. }
  39. auto LoweringHandleBoolLiteral(LoweringFunctionContext& context,
  40. SemanticsNodeId node_id, SemanticsNode node)
  41. -> void {
  42. llvm::Value* v = llvm::ConstantInt::get(context.builder().getInt1Ty(),
  43. node.GetAsBoolLiteral().index);
  44. context.SetLocal(node_id, v);
  45. }
  46. auto LoweringHandleBranch(LoweringFunctionContext& context,
  47. SemanticsNodeId /*node_id*/, SemanticsNode node)
  48. -> void {
  49. SemanticsNodeBlockId target_block_id = node.GetAsBranch();
  50. // Opportunistically avoid creating a BasicBlock that contains just a branch.
  51. llvm::BasicBlock* block = context.builder().GetInsertBlock();
  52. if (block->empty() && context.TryToReuseBlock(target_block_id, block)) {
  53. // Reuse this block as the branch target.
  54. } else {
  55. context.builder().CreateBr(context.GetBlock(target_block_id));
  56. }
  57. context.builder().ClearInsertionPoint();
  58. }
  59. auto LoweringHandleBranchIf(LoweringFunctionContext& context,
  60. SemanticsNodeId /*node_id*/, SemanticsNode node)
  61. -> void {
  62. auto [target_block_id, cond_id] = node.GetAsBranchIf();
  63. llvm::Value* cond = context.GetLocalLoaded(cond_id);
  64. llvm::BasicBlock* then_block = context.GetBlock(target_block_id);
  65. llvm::BasicBlock* else_block = context.CreateSyntheticBlock();
  66. context.builder().CreateCondBr(cond, then_block, else_block);
  67. context.builder().SetInsertPoint(else_block);
  68. }
  69. auto LoweringHandleBranchWithArg(LoweringFunctionContext& context,
  70. SemanticsNodeId /*node_id*/,
  71. SemanticsNode node) -> void {
  72. auto [target_block_id, arg_id] = node.GetAsBranchWithArg();
  73. llvm::Value* arg = context.GetLocalLoaded(arg_id);
  74. SemanticsTypeId arg_type_id =
  75. context.semantics_ir().GetNode(arg_id).type_id();
  76. // Opportunistically avoid creating a BasicBlock that contains just a branch.
  77. // We only do this for a block that we know will only have a single
  78. // predecessor, so that we can correctly populate the predecessors of the
  79. // PHINode.
  80. llvm::BasicBlock* block = context.builder().GetInsertBlock();
  81. llvm::BasicBlock* phi_predecessor = block;
  82. if (block->empty() && context.IsCurrentSyntheticBlock(block) &&
  83. context.TryToReuseBlock(target_block_id, block)) {
  84. // Reuse this block as the branch target.
  85. phi_predecessor = block->getSinglePredecessor();
  86. CARBON_CHECK(phi_predecessor)
  87. << "Synthetic block did not have a single predecessor";
  88. } else {
  89. context.builder().CreateBr(context.GetBlock(target_block_id));
  90. }
  91. context.GetBlockArg(target_block_id, arg_type_id)
  92. ->addIncoming(arg, phi_predecessor);
  93. context.builder().ClearInsertionPoint();
  94. }
  95. auto LoweringHandleBuiltin(LoweringFunctionContext& /*context*/,
  96. SemanticsNodeId /*node_id*/, SemanticsNode node)
  97. -> void {
  98. CARBON_FATAL() << "TODO: Add support: " << node;
  99. }
  100. auto LoweringHandleCall(LoweringFunctionContext& context,
  101. SemanticsNodeId node_id, SemanticsNode node) -> void {
  102. auto [refs_id, function_id] = node.GetAsCall();
  103. auto* function = context.GetFunction(function_id);
  104. std::vector<llvm::Value*> args;
  105. for (auto ref_id : context.semantics_ir().GetNodeBlock(refs_id)) {
  106. args.push_back(context.GetLocalLoaded(ref_id));
  107. }
  108. if (function->getReturnType()->isVoidTy()) {
  109. context.builder().CreateCall(function, args);
  110. // TODO: use empty tuple type.
  111. // TODO: don't create the empty tuple if the call does not get assigned.
  112. context.SetLocal(node_id, context.builder().CreateAlloca(
  113. llvm::StructType::get(context.llvm_context()),
  114. /*ArraySize=*/nullptr, "TupleLiteralValue"));
  115. } else {
  116. context.SetLocal(node_id, context.builder().CreateCall(
  117. function, args, function->getName()));
  118. }
  119. }
  120. auto LoweringHandleFunctionDeclaration(LoweringFunctionContext& /*context*/,
  121. SemanticsNodeId /*node_id*/,
  122. SemanticsNode node) -> void {
  123. CARBON_FATAL()
  124. << "Should not be encountered. If that changes, we may want to change "
  125. "higher-level logic to skip them rather than calling this. "
  126. << node;
  127. }
  128. auto LoweringHandleIndex(LoweringFunctionContext& /*context*/,
  129. SemanticsNodeId /*node_id*/, SemanticsNode node)
  130. -> void {
  131. CARBON_FATAL() << "TODO: Add support: " << node;
  132. }
  133. auto LoweringHandleIntegerLiteral(LoweringFunctionContext& context,
  134. SemanticsNodeId node_id, SemanticsNode node)
  135. -> void {
  136. llvm::APInt i =
  137. context.semantics_ir().GetIntegerLiteral(node.GetAsIntegerLiteral());
  138. // TODO: This won't offer correct semantics, but seems close enough for now.
  139. llvm::Value* v =
  140. llvm::ConstantInt::get(context.builder().getInt32Ty(), i.getSExtValue());
  141. context.SetLocal(node_id, v);
  142. }
  143. auto LoweringHandleNamespace(LoweringFunctionContext& /*context*/,
  144. SemanticsNodeId /*node_id*/,
  145. SemanticsNode /*node*/) -> void {
  146. // No action to take.
  147. }
  148. auto LoweringHandleRealLiteral(LoweringFunctionContext& context,
  149. SemanticsNodeId node_id, SemanticsNode node)
  150. -> void {
  151. SemanticsRealLiteral real =
  152. context.semantics_ir().GetRealLiteral(node.GetAsRealLiteral());
  153. // TODO: This will probably have overflow issues, and should be fixed.
  154. double val =
  155. real.mantissa.getSExtValue() *
  156. std::pow((real.is_decimal ? 10 : 2), real.exponent.getSExtValue());
  157. llvm::APFloat llvm_val(val);
  158. context.SetLocal(node_id, llvm::ConstantFP::get(
  159. context.builder().getDoubleTy(), llvm_val));
  160. }
  161. auto LoweringHandleReturn(LoweringFunctionContext& context,
  162. SemanticsNodeId /*node_id*/, SemanticsNode /*node*/)
  163. -> void {
  164. context.builder().CreateRetVoid();
  165. }
  166. auto LoweringHandleReturnExpression(LoweringFunctionContext& context,
  167. SemanticsNodeId /*node_id*/,
  168. SemanticsNode node) -> void {
  169. SemanticsNodeId expr_id = node.GetAsReturnExpression();
  170. context.builder().CreateRet(context.GetLocalLoaded(expr_id));
  171. }
  172. auto LoweringHandleStringLiteral(LoweringFunctionContext& /*context*/,
  173. SemanticsNodeId /*node_id*/,
  174. SemanticsNode node) -> void {
  175. CARBON_FATAL() << "TODO: Add support: " << node;
  176. }
  177. auto LoweringHandleStructMemberAccess(LoweringFunctionContext& context,
  178. SemanticsNodeId node_id,
  179. SemanticsNode node) -> void {
  180. auto [struct_id, member_index] = node.GetAsStructMemberAccess();
  181. auto struct_type_id = context.semantics_ir().GetNode(struct_id).type_id();
  182. auto* llvm_type = context.GetType(struct_type_id);
  183. // Get type information for member names.
  184. auto type_refs = context.semantics_ir().GetNodeBlock(
  185. context.semantics_ir()
  186. .GetNode(context.semantics_ir().GetType(struct_type_id))
  187. .GetAsStructType());
  188. auto [field_name_id, field_type_id] =
  189. context.semantics_ir()
  190. .GetNode(type_refs[member_index.index])
  191. .GetAsStructTypeField();
  192. auto member_name = context.semantics_ir().GetString(field_name_id);
  193. auto* gep = context.builder().CreateStructGEP(
  194. llvm_type, context.GetLocal(struct_id), member_index.index, member_name);
  195. context.SetLocal(node_id, gep);
  196. }
  197. auto LoweringHandleTupleValue(LoweringFunctionContext& context,
  198. SemanticsNodeId node_id, SemanticsNode node)
  199. -> void {
  200. auto* llvm_type = context.GetType(node.type_id());
  201. auto* alloca = context.builder().CreateAlloca(
  202. llvm_type, /*ArraySize=*/nullptr, "TupleLiteralValue");
  203. context.SetLocal(node_id, alloca);
  204. auto refs = context.semantics_ir().GetNodeBlock(node.GetAsTupleValue());
  205. auto type_refs = context.semantics_ir().GetTypeBlock(
  206. context.semantics_ir()
  207. .GetNode(context.semantics_ir().GetType(node.type_id()))
  208. .GetAsTupleType());
  209. for (int i = 0; i < static_cast<int>(type_refs.size()); ++i) {
  210. auto* gep = context.builder().CreateStructGEP(llvm_type, alloca, i);
  211. context.builder().CreateStore(context.GetLocal(refs[i]), gep);
  212. }
  213. }
  214. auto LoweringHandleStructTypeField(LoweringFunctionContext& /*context*/,
  215. SemanticsNodeId /*node_id*/,
  216. SemanticsNode /*node*/) -> void {
  217. // No action to take.
  218. }
  219. auto LoweringHandleStructValue(LoweringFunctionContext& context,
  220. SemanticsNodeId node_id, SemanticsNode node)
  221. -> void {
  222. auto* llvm_type = context.GetType(node.type_id());
  223. auto* alloca = context.builder().CreateAlloca(
  224. llvm_type, /*ArraySize=*/nullptr, "StructLiteralValue");
  225. context.SetLocal(node_id, alloca);
  226. auto refs = context.semantics_ir().GetNodeBlock(node.GetAsStructValue());
  227. // Get type information for member names.
  228. auto type_refs = context.semantics_ir().GetNodeBlock(
  229. context.semantics_ir()
  230. .GetNode(context.semantics_ir().GetType(node.type_id()))
  231. .GetAsStructType());
  232. for (int i = 0; i < static_cast<int>(refs.size()); ++i) {
  233. auto [field_name_id, field_type_id] =
  234. context.semantics_ir().GetNode(type_refs[i]).GetAsStructTypeField();
  235. auto member_name = context.semantics_ir().GetString(field_name_id);
  236. auto* gep =
  237. context.builder().CreateStructGEP(llvm_type, alloca, i, member_name);
  238. context.builder().CreateStore(context.GetLocal(refs[i]), gep);
  239. }
  240. }
  241. auto LoweringHandleStubReference(LoweringFunctionContext& context,
  242. SemanticsNodeId node_id, SemanticsNode node)
  243. -> void {
  244. context.SetLocal(node_id, context.GetLocal(node.GetAsStubReference()));
  245. }
  246. auto LoweringHandleUnaryOperatorNot(LoweringFunctionContext& context,
  247. SemanticsNodeId node_id, SemanticsNode node)
  248. -> void {
  249. context.SetLocal(node_id, context.builder().CreateNot(context.GetLocal(
  250. node.GetAsUnaryOperatorNot())));
  251. }
  252. auto LoweringHandleVarStorage(LoweringFunctionContext& context,
  253. SemanticsNodeId node_id, SemanticsNode node)
  254. -> void {
  255. // TODO: This should provide a name, not just `var`. Also, LLVM requires
  256. // globals to have a name. Do we want to generate a name, which would need to
  257. // be consistent across translation units, or use the given name, which
  258. // requires either looking ahead for BindName or restructuring semantics,
  259. // either of which affects the destructuring due to the difference in
  260. // storage?
  261. auto* alloca = context.builder().CreateAlloca(context.GetType(node.type_id()),
  262. /*ArraySize=*/nullptr, "var");
  263. context.SetLocal(node_id, alloca);
  264. }
  265. } // namespace Carbon