|
20 | 20 |
|
21 | 21 | #include "absl/container/flat_hash_map.h"
|
22 | 22 | #include "absl/container/flat_hash_set.h"
|
| 23 | +#include "labm8/cpp/logging.h" |
23 | 24 | #include "labm8/cpp/status_macros.h"
|
24 | 25 | #include "labm8/cpp/string.h"
|
25 | 26 | #include "llvm/IR/BasicBlock.h"
|
@@ -323,29 +324,131 @@ Node* ProgramGraphBuilder::AddLlvmInstruction(const ::llvm::Instruction* instruc
|
323 | 324 | Node* ProgramGraphBuilder::AddLlvmVariable(const ::llvm::Instruction* operand,
|
324 | 325 | const programl::Function* function) {
|
325 | 326 | const LlvmTextComponents text = textEncoder_.Encode(operand);
|
326 |
| - Node* node = AddVariable(text.lhs_type, function); |
| 327 | + Node* node = AddVariable("var", function); |
327 | 328 | node->set_block(blockCount_);
|
328 | 329 | graph::AddScalarFeature(node, "full_text", text.lhs);
|
329 | 330 |
|
| 331 | + compositeTypeParts_.clear(); // Reset after previous call. |
| 332 | + Node* type = GetOrCreateType(operand->getType()); |
| 333 | + CHECK(AddTypeEdge(/*position=*/0, type, node).ok()); |
| 334 | + |
330 | 335 | return node;
|
331 | 336 | }
|
332 | 337 |
|
333 | 338 | Node* ProgramGraphBuilder::AddLlvmVariable(const ::llvm::Argument* argument,
|
334 | 339 | const programl::Function* function) {
|
335 | 340 | const LlvmTextComponents text = textEncoder_.Encode(argument);
|
336 |
| - Node* node = AddVariable(text.lhs_type, function); |
| 341 | + Node* node = AddVariable("var", function); |
337 | 342 | node->set_block(blockCount_);
|
338 | 343 | graph::AddScalarFeature(node, "full_text", text.lhs);
|
339 | 344 |
|
| 345 | + compositeTypeParts_.clear(); // Reset after previous call. |
| 346 | + Node* type = GetOrCreateType(argument->getType()); |
| 347 | + CHECK(AddTypeEdge(/*position=*/0, type, node).ok()); |
| 348 | + |
340 | 349 | return node;
|
341 | 350 | }
|
342 | 351 |
|
343 | 352 | Node* ProgramGraphBuilder::AddLlvmConstant(const ::llvm::Constant* constant) {
|
344 | 353 | const LlvmTextComponents text = textEncoder_.Encode(constant);
|
345 |
| - Node* node = AddConstant(text.lhs_type); |
| 354 | + Node* node = AddConstant("val"); |
346 | 355 | node->set_block(blockCount_);
|
347 | 356 | graph::AddScalarFeature(node, "full_text", text.text);
|
348 | 357 |
|
| 358 | + compositeTypeParts_.clear(); // Reset after previous call. |
| 359 | + Node* type = GetOrCreateType(constant->getType()); |
| 360 | + CHECK(AddTypeEdge(/*position=*/0, type, node).ok()); |
| 361 | + |
| 362 | + return node; |
| 363 | +} |
| 364 | + |
| 365 | +Node* ProgramGraphBuilder::AddLlvmType(const ::llvm::Type* type) { |
| 366 | + // Dispatch to the type-specific handlers. |
| 367 | + if (::llvm::dyn_cast<::llvm::StructType>(type)) { |
| 368 | + return AddLlvmType(::llvm::dyn_cast<::llvm::StructType>(type)); |
| 369 | + } else if (::llvm::dyn_cast<::llvm::PointerType>(type)) { |
| 370 | + return AddLlvmType(::llvm::dyn_cast<::llvm::PointerType>(type)); |
| 371 | + } else if (::llvm::dyn_cast<::llvm::FunctionType>(type)) { |
| 372 | + return AddLlvmType(::llvm::dyn_cast<::llvm::FunctionType>(type)); |
| 373 | + } else if (::llvm::dyn_cast<::llvm::ArrayType>(type)) { |
| 374 | + return AddLlvmType(::llvm::dyn_cast<::llvm::ArrayType>(type)); |
| 375 | + } else if (::llvm::dyn_cast<::llvm::VectorType>(type)) { |
| 376 | + return AddLlvmType(::llvm::dyn_cast<::llvm::VectorType>(type)); |
| 377 | + } else { |
| 378 | + const LlvmTextComponents text = textEncoder_.Encode(type); |
| 379 | + Node* node = AddType(text.text); |
| 380 | + graph::AddScalarFeature(node, "llvm_string", text.text); |
| 381 | + return node; |
| 382 | + } |
| 383 | +} |
| 384 | + |
| 385 | +Node* ProgramGraphBuilder::AddLlvmType(const ::llvm::StructType* type) { |
| 386 | + Node* node = AddType("struct"); |
| 387 | + compositeTypeParts_[type] = node; |
| 388 | + graph::AddScalarFeature(node, "llvm_string", textEncoder_.Encode(type).text); |
| 389 | + |
| 390 | + // Add types for the struct elements, and add type edges. |
| 391 | + for (int i = 0; i < type->getNumElements(); ++i) { |
| 392 | + const auto& member = type->elements()[i]; |
| 393 | + // Don't re-use member types in structs, always create a new type. For |
| 394 | + // example, the code: |
| 395 | + // |
| 396 | + // struct S { |
| 397 | + // int a; |
| 398 | + // int b; |
| 399 | + // }; |
| 400 | + // int c; |
| 401 | + // int d; |
| 402 | + // |
| 403 | + // would produce four type nodes: one for S.a, one for S.b, and one which |
| 404 | + // is shared by c and d. |
| 405 | + Node* memberNode = AddLlvmType(member); |
| 406 | + CHECK(AddTypeEdge(/*position=*/i, memberNode, node).ok()); |
| 407 | + } |
| 408 | + |
| 409 | + return node; |
| 410 | +} |
| 411 | + |
| 412 | +Node* ProgramGraphBuilder::AddLlvmType(const ::llvm::PointerType* type) { |
| 413 | + Node* node = AddType("*"); |
| 414 | + graph::AddScalarFeature(node, "llvm_string", textEncoder_.Encode(type).text); |
| 415 | + |
| 416 | + auto elementType = type->getElementType(); |
| 417 | + auto parent = compositeTypeParts_.find(elementType); |
| 418 | + if (parent == compositeTypeParts_.end()) { |
| 419 | + // Re-use the type if it already exists to prevent duplication. |
| 420 | + auto elementNode = GetOrCreateType(type->getElementType()); |
| 421 | + CHECK(AddTypeEdge(/*position=*/0, elementNode, node).ok()); |
| 422 | + } else { |
| 423 | + // Bottom-out for self-referencing types. |
| 424 | + CHECK(AddTypeEdge(/*position=*/0, parent->second, node).ok()); |
| 425 | + } |
| 426 | + |
| 427 | + return node; |
| 428 | +} |
| 429 | + |
| 430 | +Node* ProgramGraphBuilder::AddLlvmType(const ::llvm::FunctionType* type) { |
| 431 | + const std::string signature = textEncoder_.Encode(type).text; |
| 432 | + Node* node = AddType(signature); |
| 433 | + graph::AddScalarFeature(node, "llvm_string", signature); |
| 434 | + return node; |
| 435 | +} |
| 436 | + |
| 437 | +Node* ProgramGraphBuilder::AddLlvmType(const ::llvm::ArrayType* type) { |
| 438 | + Node* node = AddType("[]"); |
| 439 | + graph::AddScalarFeature(node, "llvm_string", textEncoder_.Encode(type).text); |
| 440 | + // Re-use the type if it already exists to prevent duplication. |
| 441 | + auto elementType = GetOrCreateType(type->getElementType()); |
| 442 | + CHECK(AddTypeEdge(/*position=*/0, elementType, node).ok()); |
| 443 | + return node; |
| 444 | +} |
| 445 | + |
| 446 | +Node* ProgramGraphBuilder::AddLlvmType(const ::llvm::VectorType* type) { |
| 447 | + Node* node = AddType("vector"); |
| 448 | + graph::AddScalarFeature(node, "llvm_string", textEncoder_.Encode(type).text); |
| 449 | + // Re-use the type if it already exists to prevent duplication. |
| 450 | + auto elementType = GetOrCreateType(type->getElementType()); |
| 451 | + CHECK(AddTypeEdge(/*position=*/0, elementType, node).ok()); |
349 | 452 | return node;
|
350 | 453 | }
|
351 | 454 |
|
@@ -461,6 +564,16 @@ void ProgramGraphBuilder::Clear() {
|
461 | 564 | programl::graph::ProgramGraphBuilder::Clear();
|
462 | 565 | }
|
463 | 566 |
|
| 567 | +Node* ProgramGraphBuilder::GetOrCreateType(const ::llvm::Type* type) { |
| 568 | + auto it = types_.find(type); |
| 569 | + if (it == types_.end()) { |
| 570 | + Node* node = AddLlvmType(type); |
| 571 | + types_[type] = node; |
| 572 | + return node; |
| 573 | + } |
| 574 | + return it->second; |
| 575 | +} |
| 576 | + |
464 | 577 | } // namespace internal
|
465 | 578 | } // namespace llvm
|
466 | 579 | } // namespace ir
|
|
0 commit comments