handle.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  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 "llvm/ADT/STLExtras.h"
  5. #include "llvm/ADT/Sequence.h"
  6. #include "toolchain/lower/function_context.h"
  7. #include "toolchain/sem_ir/node_kind.h"
  8. namespace Carbon::Lower {
  9. auto HandleInvalid(FunctionContext& /*context*/, SemIR::NodeId /*node_id*/,
  10. SemIR::Node /*node*/) -> void {
  11. llvm_unreachable("never in actual IR");
  12. }
  13. auto HandleCrossReference(FunctionContext& /*context*/,
  14. SemIR::NodeId /*node_id*/, SemIR::Node node) -> void {
  15. CARBON_FATAL() << "TODO: Add support: " << node;
  16. }
  17. auto HandleAddressOf(FunctionContext& context, SemIR::NodeId node_id,
  18. SemIR::Node node) -> void {
  19. context.SetLocal(node_id, context.GetLocal(node.GetAsAddressOf()));
  20. }
  21. auto HandleArrayIndex(FunctionContext& context, SemIR::NodeId node_id,
  22. SemIR::Node node) -> void {
  23. auto [array_node_id, index_node_id] = node.GetAsArrayIndex();
  24. auto* array_value = context.GetLocal(array_node_id);
  25. auto* llvm_type =
  26. context.GetType(context.semantics_ir().GetNode(array_node_id).type_id());
  27. auto index_node = context.semantics_ir().GetNode(index_node_id);
  28. llvm::Value* array_element_value;
  29. if (index_node.kind() == SemIR::NodeKind::IntegerLiteral) {
  30. const auto index = context.semantics_ir()
  31. .GetIntegerLiteral(index_node.GetAsIntegerLiteral())
  32. .getZExtValue();
  33. array_element_value = context.GetIndexFromStructOrArray(
  34. llvm_type, array_value, index, "array.index");
  35. } else {
  36. auto* index = context.GetLocalLoaded(index_node_id);
  37. // TODO: Handle return value or call such as `F()[a]`.
  38. auto* zero = llvm::ConstantInt::get(
  39. llvm::Type::getInt32Ty(context.llvm_context()), 0);
  40. array_element_value = context.builder().CreateInBoundsGEP(
  41. llvm_type, array_value, {zero, index}, "array.index");
  42. }
  43. context.SetLocal(node_id, array_element_value);
  44. }
  45. auto HandleArrayInit(FunctionContext& context, SemIR::NodeId node_id,
  46. SemIR::Node node) -> void {
  47. auto [src_id, refs_id] = node.GetAsArrayInit();
  48. // The result of initialization is the return slot of the initializer.
  49. context.SetLocal(
  50. node_id,
  51. context.GetLocal(context.semantics_ir().GetNodeBlock(refs_id).back()));
  52. }
  53. auto HandleAssign(FunctionContext& context, SemIR::NodeId /*node_id*/,
  54. SemIR::Node node) -> void {
  55. auto [storage_id, value_id] = node.GetAsAssign();
  56. auto storage_type_id = context.semantics_ir().GetNode(storage_id).type_id();
  57. context.FinishInitialization(storage_type_id, storage_id, value_id);
  58. }
  59. auto HandleBinaryOperatorAdd(FunctionContext& /*context*/,
  60. SemIR::NodeId /*node_id*/, SemIR::Node node)
  61. -> void {
  62. CARBON_FATAL() << "TODO: Add support: " << node;
  63. }
  64. auto HandleBindName(FunctionContext& /*context*/, SemIR::NodeId /*node_id*/,
  65. SemIR::Node /*node*/) -> void {
  66. // Probably need to do something here, but not necessary for now.
  67. }
  68. auto HandleBlockArg(FunctionContext& context, SemIR::NodeId node_id,
  69. SemIR::Node node) -> void {
  70. SemIR::NodeBlockId block_id = node.GetAsBlockArg();
  71. context.SetLocal(node_id, context.GetBlockArg(block_id, node.type_id()));
  72. }
  73. auto HandleBoolLiteral(FunctionContext& context, SemIR::NodeId node_id,
  74. SemIR::Node node) -> void {
  75. llvm::Value* v = llvm::ConstantInt::get(context.builder().getInt1Ty(),
  76. node.GetAsBoolLiteral().index);
  77. context.SetLocal(node_id, v);
  78. }
  79. auto HandleBranch(FunctionContext& context, SemIR::NodeId /*node_id*/,
  80. SemIR::Node node) -> void {
  81. SemIR::NodeBlockId target_block_id = node.GetAsBranch();
  82. // Opportunistically avoid creating a BasicBlock that contains just a branch.
  83. llvm::BasicBlock* block = context.builder().GetInsertBlock();
  84. if (block->empty() && context.TryToReuseBlock(target_block_id, block)) {
  85. // Reuse this block as the branch target.
  86. } else {
  87. context.builder().CreateBr(context.GetBlock(target_block_id));
  88. }
  89. context.builder().ClearInsertionPoint();
  90. }
  91. auto HandleBranchIf(FunctionContext& context, SemIR::NodeId /*node_id*/,
  92. SemIR::Node node) -> void {
  93. auto [target_block_id, cond_id] = node.GetAsBranchIf();
  94. llvm::Value* cond = context.GetLocalLoaded(cond_id);
  95. llvm::BasicBlock* then_block = context.GetBlock(target_block_id);
  96. llvm::BasicBlock* else_block = context.CreateSyntheticBlock();
  97. context.builder().CreateCondBr(cond, then_block, else_block);
  98. context.builder().SetInsertPoint(else_block);
  99. }
  100. auto HandleBranchWithArg(FunctionContext& context, SemIR::NodeId /*node_id*/,
  101. SemIR::Node node) -> void {
  102. auto [target_block_id, arg_id] = node.GetAsBranchWithArg();
  103. llvm::Value* arg = context.GetLocalLoaded(arg_id);
  104. SemIR::TypeId arg_type_id = context.semantics_ir().GetNode(arg_id).type_id();
  105. // Opportunistically avoid creating a BasicBlock that contains just a branch.
  106. // We only do this for a block that we know will only have a single
  107. // predecessor, so that we can correctly populate the predecessors of the
  108. // PHINode.
  109. llvm::BasicBlock* block = context.builder().GetInsertBlock();
  110. llvm::BasicBlock* phi_predecessor = block;
  111. if (block->empty() && context.IsCurrentSyntheticBlock(block) &&
  112. context.TryToReuseBlock(target_block_id, block)) {
  113. // Reuse this block as the branch target.
  114. phi_predecessor = block->getSinglePredecessor();
  115. CARBON_CHECK(phi_predecessor)
  116. << "Synthetic block did not have a single predecessor";
  117. } else {
  118. context.builder().CreateBr(context.GetBlock(target_block_id));
  119. }
  120. context.GetBlockArg(target_block_id, arg_type_id)
  121. ->addIncoming(arg, phi_predecessor);
  122. context.builder().ClearInsertionPoint();
  123. }
  124. auto HandleBuiltin(FunctionContext& /*context*/, SemIR::NodeId /*node_id*/,
  125. SemIR::Node node) -> void {
  126. CARBON_FATAL() << "TODO: Add support: " << node;
  127. }
  128. auto HandleCall(FunctionContext& context, SemIR::NodeId node_id,
  129. SemIR::Node node) -> void {
  130. auto [refs_id, function_id] = node.GetAsCall();
  131. auto* llvm_function = context.GetFunction(function_id);
  132. const auto& function = context.semantics_ir().GetFunction(function_id);
  133. std::vector<llvm::Value*> args;
  134. llvm::ArrayRef<SemIR::NodeId> arg_ids =
  135. context.semantics_ir().GetNodeBlock(refs_id);
  136. if (function.return_slot_id.is_valid()) {
  137. args.push_back(context.GetLocal(arg_ids.back()));
  138. arg_ids = arg_ids.drop_back();
  139. }
  140. for (auto ref_id : arg_ids) {
  141. auto arg_type_id = context.semantics_ir().GetNode(ref_id).type_id();
  142. switch (SemIR::GetValueRepresentation(context.semantics_ir(), arg_type_id)
  143. .kind) {
  144. case SemIR::ValueRepresentation::None:
  145. break;
  146. case SemIR::ValueRepresentation::Copy:
  147. case SemIR::ValueRepresentation::Custom:
  148. args.push_back(context.GetLocalLoaded(ref_id));
  149. break;
  150. case SemIR::ValueRepresentation::Pointer:
  151. args.push_back(context.GetLocal(ref_id));
  152. break;
  153. }
  154. }
  155. if (llvm_function->getReturnType()->isVoidTy()) {
  156. context.builder().CreateCall(llvm_function, args);
  157. // The value of a function call with a void return type shouldn't used, but
  158. // StubReference needs a value to propagate.
  159. context.SetLocal(node_id,
  160. llvm::PoisonValue::get(context.GetType(node.type_id())));
  161. } else {
  162. context.SetLocal(node_id,
  163. context.builder().CreateCall(llvm_function, args,
  164. llvm_function->getName()));
  165. }
  166. }
  167. auto HandleDereference(FunctionContext& context, SemIR::NodeId node_id,
  168. SemIR::Node node) -> void {
  169. context.SetLocal(node_id, context.GetLocal(node.GetAsDereference()));
  170. }
  171. auto HandleFunctionDeclaration(FunctionContext& /*context*/,
  172. SemIR::NodeId /*node_id*/, SemIR::Node node)
  173. -> void {
  174. CARBON_FATAL()
  175. << "Should not be encountered. If that changes, we may want to change "
  176. "higher-level logic to skip them rather than calling this. "
  177. << node;
  178. }
  179. auto HandleInitializeFrom(FunctionContext& context, SemIR::NodeId /*node_id*/,
  180. SemIR::Node node) -> void {
  181. auto [init_id, storage_id] = node.GetAsInitializeFrom();
  182. auto storage_type_id = context.semantics_ir().GetNode(storage_id).type_id();
  183. context.FinishInitialization(storage_type_id, storage_id, init_id);
  184. }
  185. auto HandleIntegerLiteral(FunctionContext& context, SemIR::NodeId node_id,
  186. SemIR::Node node) -> void {
  187. llvm::APInt i =
  188. context.semantics_ir().GetIntegerLiteral(node.GetAsIntegerLiteral());
  189. // TODO: This won't offer correct semantics, but seems close enough for now.
  190. llvm::Value* v =
  191. llvm::ConstantInt::get(context.builder().getInt32Ty(), i.getZExtValue());
  192. context.SetLocal(node_id, v);
  193. }
  194. auto HandleNamespace(FunctionContext& /*context*/, SemIR::NodeId /*node_id*/,
  195. SemIR::Node /*node*/) -> void {
  196. // No action to take.
  197. }
  198. auto HandleNoOp(FunctionContext& /*context*/, SemIR::NodeId /*node_id*/,
  199. SemIR::Node /*node*/) -> void {
  200. // No action to take.
  201. }
  202. auto HandleParameter(FunctionContext& /*context*/, SemIR::NodeId /*node_id*/,
  203. SemIR::Node /*node*/) -> void {
  204. CARBON_FATAL() << "Parameters should be lowered by `BuildFunctionDefinition`";
  205. }
  206. auto HandleRealLiteral(FunctionContext& context, SemIR::NodeId node_id,
  207. SemIR::Node node) -> void {
  208. SemIR::RealLiteral real =
  209. context.semantics_ir().GetRealLiteral(node.GetAsRealLiteral());
  210. // TODO: This will probably have overflow issues, and should be fixed.
  211. double val =
  212. real.mantissa.getZExtValue() *
  213. std::pow((real.is_decimal ? 10 : 2), real.exponent.getSExtValue());
  214. llvm::APFloat llvm_val(val);
  215. context.SetLocal(node_id, llvm::ConstantFP::get(
  216. context.builder().getDoubleTy(), llvm_val));
  217. }
  218. auto HandleReturn(FunctionContext& context, SemIR::NodeId /*node_id*/,
  219. SemIR::Node /*node*/) -> void {
  220. context.builder().CreateRetVoid();
  221. }
  222. auto HandleReturnExpression(FunctionContext& context, SemIR::NodeId /*node_id*/,
  223. SemIR::Node node) -> void {
  224. SemIR::NodeId expr_id = node.GetAsReturnExpression();
  225. switch (SemIR::GetInitializingRepresentation(
  226. context.semantics_ir(),
  227. context.semantics_ir().GetNode(expr_id).type_id())
  228. .kind) {
  229. case SemIR::InitializingRepresentation::None:
  230. case SemIR::InitializingRepresentation::InPlace:
  231. // Nothing to return.
  232. context.builder().CreateRetVoid();
  233. return;
  234. case SemIR::InitializingRepresentation::ByCopy:
  235. // The expression produces the value representation for the type.
  236. context.builder().CreateRet(context.GetLocalLoaded(expr_id));
  237. return;
  238. }
  239. }
  240. auto HandleStringLiteral(FunctionContext& /*context*/,
  241. SemIR::NodeId /*node_id*/, SemIR::Node node) -> void {
  242. CARBON_FATAL() << "TODO: Add support: " << node;
  243. }
  244. auto HandleStructAccess(FunctionContext& context, SemIR::NodeId node_id,
  245. SemIR::Node node) -> void {
  246. auto [struct_id, member_index] = node.GetAsStructAccess();
  247. auto struct_type_id = context.semantics_ir().GetNode(struct_id).type_id();
  248. auto* llvm_type = context.GetType(struct_type_id);
  249. // Get type information for member names.
  250. auto type_refs = context.semantics_ir().GetNodeBlock(
  251. context.semantics_ir()
  252. .GetNode(context.semantics_ir().GetType(struct_type_id))
  253. .GetAsStructType());
  254. auto [field_name_id, field_type_id] =
  255. context.semantics_ir()
  256. .GetNode(type_refs[member_index.index])
  257. .GetAsStructTypeField();
  258. auto member_name = context.semantics_ir().GetString(field_name_id);
  259. auto* gep = context.builder().CreateStructGEP(
  260. llvm_type, context.GetLocal(struct_id), member_index.index, member_name);
  261. context.SetLocal(node_id, gep);
  262. }
  263. auto HandleStructLiteral(FunctionContext& context, SemIR::NodeId node_id,
  264. SemIR::Node node) -> void {
  265. // A StructLiteral should always be converted to a StructInit or StructValue
  266. // if its value is needed.
  267. context.SetLocal(node_id,
  268. llvm::PoisonValue::get(context.GetType(node.type_id())));
  269. }
  270. // Emits the value representation for a struct or tuple whose elements are the
  271. // contents of `refs_id`.
  272. auto EmitStructOrTupleValueRepresentation(FunctionContext& context,
  273. SemIR::TypeId type_id,
  274. SemIR::NodeBlockId refs_id,
  275. llvm::Twine name) -> llvm::Value* {
  276. auto* llvm_type = context.GetType(type_id);
  277. switch (SemIR::GetValueRepresentation(context.semantics_ir(), type_id).kind) {
  278. case SemIR::ValueRepresentation::None:
  279. // TODO: Add a helper to get a "no value representation" value.
  280. return llvm::PoisonValue::get(llvm_type);
  281. case SemIR::ValueRepresentation::Copy: {
  282. auto refs = context.semantics_ir().GetNodeBlock(refs_id);
  283. CARBON_CHECK(refs.size() == 1)
  284. << "Unexpected size for aggregate with by-copy value representation";
  285. // TODO: Remove the LLVM StructType wrapper in this case, so we don't
  286. // need this `insert_value` wrapping.
  287. return context.builder().CreateInsertValue(
  288. llvm::PoisonValue::get(llvm_type), context.GetLocal(refs[0]), {0});
  289. }
  290. case SemIR::ValueRepresentation::Pointer: {
  291. // Write the object representation to a local alloca so we can produce a
  292. // pointer to it as the value representation.
  293. auto* alloca = context.builder().CreateAlloca(
  294. llvm_type, /*ArraySize=*/nullptr, name);
  295. for (auto [i, ref] :
  296. llvm::enumerate(context.semantics_ir().GetNodeBlock(refs_id))) {
  297. auto* gep = context.builder().CreateStructGEP(llvm_type, alloca, i);
  298. // TODO: We are loading a value representation here and storing an
  299. // object representation!
  300. context.builder().CreateStore(context.GetLocal(ref), gep);
  301. }
  302. return alloca;
  303. }
  304. case SemIR::ValueRepresentation::Custom:
  305. CARBON_FATAL()
  306. << "Aggregate should never have custom value representation";
  307. }
  308. }
  309. auto HandleStructInit(FunctionContext& context, SemIR::NodeId node_id,
  310. SemIR::Node node) -> void {
  311. auto* llvm_type = context.GetType(node.type_id());
  312. switch (SemIR::GetInitializingRepresentation(context.semantics_ir(),
  313. node.type_id())
  314. .kind) {
  315. case SemIR::InitializingRepresentation::None:
  316. case SemIR::InitializingRepresentation::InPlace:
  317. // TODO: Add a helper to poison a value slot.
  318. context.SetLocal(node_id, llvm::PoisonValue::get(llvm_type));
  319. break;
  320. case SemIR::InitializingRepresentation::ByCopy: {
  321. auto [struct_literal_id, refs_id] = node.GetAsStructInit();
  322. context.SetLocal(node_id,
  323. EmitStructOrTupleValueRepresentation(
  324. context, node.type_id(), refs_id, "struct.init"));
  325. break;
  326. }
  327. }
  328. }
  329. auto HandleStructValue(FunctionContext& context, SemIR::NodeId node_id,
  330. SemIR::Node node) -> void {
  331. auto [struct_literal_id, refs_id] = node.GetAsStructValue();
  332. context.SetLocal(node_id, EmitStructOrTupleValueRepresentation(
  333. context, node.type_id(), refs_id, "struct"));
  334. }
  335. auto HandleStructTypeField(FunctionContext& /*context*/,
  336. SemIR::NodeId /*node_id*/, SemIR::Node /*node*/)
  337. -> void {
  338. // No action to take.
  339. }
  340. auto HandleStubReference(FunctionContext& context, SemIR::NodeId node_id,
  341. SemIR::Node node) -> void {
  342. context.SetLocal(node_id, context.GetLocal(node.GetAsStubReference()));
  343. }
  344. auto HandleTupleAccess(FunctionContext& context, SemIR::NodeId node_id,
  345. SemIR::Node node) -> void {
  346. auto [tuple_node_id, index] = node.GetAsTupleAccess();
  347. auto* tuple_value = context.GetLocal(tuple_node_id);
  348. auto* llvm_type =
  349. context.GetType(context.semantics_ir().GetNode(tuple_node_id).type_id());
  350. context.SetLocal(
  351. node_id, context.GetIndexFromStructOrArray(llvm_type, tuple_value,
  352. index.index, "tuple.elem"));
  353. }
  354. auto HandleTupleIndex(FunctionContext& context, SemIR::NodeId node_id,
  355. SemIR::Node node) -> void {
  356. auto [tuple_node_id, index_node_id] = node.GetAsTupleIndex();
  357. auto* tuple_value = context.GetLocal(tuple_node_id);
  358. auto index_node = context.semantics_ir().GetNode(index_node_id);
  359. const auto index = context.semantics_ir()
  360. .GetIntegerLiteral(index_node.GetAsIntegerLiteral())
  361. .getZExtValue();
  362. auto* llvm_type =
  363. context.GetType(context.semantics_ir().GetNode(tuple_node_id).type_id());
  364. context.SetLocal(node_id, context.GetIndexFromStructOrArray(
  365. llvm_type, tuple_value, index, "tuple.index"));
  366. }
  367. auto HandleTupleLiteral(FunctionContext& context, SemIR::NodeId node_id,
  368. SemIR::Node node) -> void {
  369. // A TupleLiteral should always be converted to a TupleInit or TupleValue if
  370. // its value is needed.
  371. context.SetLocal(node_id,
  372. llvm::PoisonValue::get(context.GetType(node.type_id())));
  373. }
  374. auto HandleTupleInit(FunctionContext& context, SemIR::NodeId node_id,
  375. SemIR::Node node) -> void {
  376. auto* llvm_type = context.GetType(node.type_id());
  377. switch (SemIR::GetInitializingRepresentation(context.semantics_ir(),
  378. node.type_id())
  379. .kind) {
  380. case SemIR::InitializingRepresentation::None:
  381. case SemIR::InitializingRepresentation::InPlace:
  382. // TODO: Add a helper to poison a value slot.
  383. context.SetLocal(node_id, llvm::PoisonValue::get(llvm_type));
  384. break;
  385. case SemIR::InitializingRepresentation::ByCopy: {
  386. auto [struct_literal_id, refs_id] = node.GetAsTupleInit();
  387. context.SetLocal(
  388. node_id, EmitStructOrTupleValueRepresentation(context, node.type_id(),
  389. refs_id, "tuple.init"));
  390. break;
  391. }
  392. }
  393. }
  394. auto HandleTupleValue(FunctionContext& context, SemIR::NodeId node_id,
  395. SemIR::Node node) -> void {
  396. auto [struct_literal_id, refs_id] = node.GetAsTupleValue();
  397. context.SetLocal(node_id, EmitStructOrTupleValueRepresentation(
  398. context, node.type_id(), refs_id, "tuple"));
  399. }
  400. auto HandleUnaryOperatorNot(FunctionContext& context, SemIR::NodeId node_id,
  401. SemIR::Node node) -> void {
  402. context.SetLocal(node_id, context.builder().CreateNot(context.GetLocal(
  403. node.GetAsUnaryOperatorNot())));
  404. }
  405. auto HandleVarStorage(FunctionContext& context, SemIR::NodeId node_id,
  406. SemIR::Node node) -> void {
  407. // TODO: Eventually this name will be optional, and we'll want to provide
  408. // something like `var` as a default. However, that's not possible right now
  409. // so cannot be tested.
  410. auto name = context.semantics_ir().GetString(node.GetAsVarStorage());
  411. auto* alloca = context.builder().CreateAlloca(context.GetType(node.type_id()),
  412. /*ArraySize=*/nullptr, name);
  413. context.SetLocal(node_id, alloca);
  414. }
  415. } // namespace Carbon::Lower