1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
use crate::constant::Constant;
use crate::name::Name;
use crate::types::{Type, Typed};
use std::collections::HashMap;

#[derive(PartialEq, Clone, Debug)]
pub enum Operand {
    /// e.g., `i32 %foo`
    LocalOperand {
        name: Name,
        ty: Type,
    },
    /// includes [`GlobalReference`](../constant/enum.Constant.html#variant.GlobalReference) for things like `@foo`
    ConstantOperand(Constant),
    MetadataOperand, // --TODO not yet implemented-- MetadataOperand(Box<Metadata>),
}

impl Typed for Operand {
    fn get_type(&self) -> Type {
        match self {
            Operand::LocalOperand { ty, .. } => ty.clone(),
            Operand::ConstantOperand(c) => c.get_type(),
            Operand::MetadataOperand => Type::MetadataType,
        }
    }
}

// ********* //
// from_llvm //
// ********* //

use crate::constant::GlobalNameMap;
use crate::from_llvm::*;
use crate::types::TyNameMap;
use llvm_sys::LLVMValueKind;

pub(crate) type ValToNameMap = HashMap<LLVMValueRef, Name>;

impl Operand {
    pub(crate) fn from_llvm_ref(
        operand: LLVMValueRef,
        vnmap: &ValToNameMap,
        gnmap: &GlobalNameMap,
        tnmap: &mut TyNameMap,
    ) -> Self {
        let constant = unsafe { LLVMIsAConstant(operand) };
        if !constant.is_null() {
            Operand::ConstantOperand(Constant::from_llvm_ref(constant, gnmap, tnmap))
        } else if unsafe {
            LLVMGetValueKind(operand) == LLVMValueKind::LLVMMetadataAsValueValueKind
        } {
            Operand::MetadataOperand
        } else {
            Operand::LocalOperand {
                name: vnmap
                    .get(&operand)
                    .unwrap_or_else(|| {
                        let names: Vec<_> = vnmap.values().collect();
                        let kind = unsafe { LLVMGetValueKind(operand) };
                        panic!(
                            "Failed to find operand with kind {:?} in vnmap; have names {:?}",
                            kind, names
                        )
                    })
                    .clone(),
                ty: Type::from_llvm_ref(unsafe { LLVMTypeOf(operand) }, tnmap),
            }
        }
    }
}