| 498 | } |
| 499 | |
| 500 | static LLVM::Value toLLVMConstantZero( |
| 501 | LLVM::Context LLContext, const ValType &ValType, |
| 502 | Span<const AST::CompositeType *const> CompositeTypes) noexcept { |
| 503 | switch (ValType.getCode()) { |
| 504 | case TypeCode::I32: |
| 505 | return LLVM::Value::getConstNull(LLContext.getInt32Ty()); |
| 506 | case TypeCode::I64: |
| 507 | return LLVM::Value::getConstNull(LLContext.getInt64Ty()); |
| 508 | case TypeCode::Ref: |
| 509 | case TypeCode::RefNull: { |
| 510 | std::array<uint8_t, 16> Data{}; |
| 511 | if (ValType.isAbsHeapType()) { |
| 512 | // Abstract heap types are already fine for null refs. |
| 513 | const auto Raw = ValType.getRawData(); |
| 514 | std::copy(Raw.begin(), Raw.end(), Data.begin()); |
| 515 | } else { |
| 516 | // For non-abstract heap types (concrete type indices), convert to the |
| 517 | // abstract heap type so that ref.cast/ref.test won't dereference a null |
| 518 | // pointer when checking the type. |
| 519 | assuming(ValType.getTypeIndex() < CompositeTypes.size()); |
| 520 | const auto *CompType = CompositeTypes[ValType.getTypeIndex()]; |
| 521 | assuming(CompType != nullptr); |
| 522 | WasmEdge::ValType VType = |
| 523 | CompType->isFunc() ? TypeCode::NullFuncRef : TypeCode::NullRef; |
| 524 | std::copy_n(VType.getRawData().cbegin(), 8, Data.begin()); |
| 525 | } |
| 526 | return LLVM::Value::getConstVector8(LLContext, Data); |
| 527 | } |
| 528 | case TypeCode::V128: |
| 529 | return LLVM::Value::getConstNull( |
| 530 | LLVM::Type::getVectorType(LLContext.getInt64Ty(), 2)); |
| 531 | case TypeCode::F32: |
| 532 | return LLVM::Value::getConstNull(LLContext.getFloatTy()); |
| 533 | case TypeCode::F64: |
| 534 | return LLVM::Value::getConstNull(LLContext.getDoubleTy()); |
| 535 | default: |
| 536 | assumingUnreachable(); |
| 537 | } |
| 538 | } |
| 539 | |
| 540 | class FunctionCompiler { |
| 541 | struct Control; |
no test coverage detected