summaryrefslogtreecommitdiff
path: root/rust/src/medium_level_il/lift.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/src/medium_level_il/lift.rs')
-rw-r--r--rust/src/medium_level_il/lift.rs510
1 files changed, 510 insertions, 0 deletions
diff --git a/rust/src/medium_level_il/lift.rs b/rust/src/medium_level_il/lift.rs
new file mode 100644
index 00000000..d6cceb18
--- /dev/null
+++ b/rust/src/medium_level_il/lift.rs
@@ -0,0 +1,510 @@
+use std::collections::BTreeMap;
+
+use super::operation::*;
+use super::{MediumLevelILFunction, MediumLevelInstructionIndex};
+use crate::architecture::CoreIntrinsic;
+use crate::rc::Ref;
+use crate::variable::{ConstantData, SSAVariable, Variable};
+
+#[derive(Clone)]
+pub enum MediumLevelILLiftedOperand {
+ ConstantData(ConstantData),
+ Intrinsic(CoreIntrinsic),
+ Expr(MediumLevelILLiftedInstruction),
+ ExprList(Vec<MediumLevelILLiftedInstruction>),
+ Float(f64),
+ Int(u64),
+ IntList(Vec<u64>),
+ TargetMap(BTreeMap<u64, MediumLevelInstructionIndex>),
+ Var(Variable),
+ VarList(Vec<Variable>),
+ VarSsa(SSAVariable),
+ VarSsaList(Vec<SSAVariable>),
+ InstructionIndex(MediumLevelInstructionIndex),
+}
+
+#[derive(Clone, Debug, PartialEq)]
+pub struct MediumLevelILLiftedInstruction {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
+ pub index: MediumLevelInstructionIndex,
+ pub size: usize,
+ pub kind: MediumLevelILLiftedInstructionKind,
+}
+
+#[derive(Clone, Debug, PartialEq)]
+pub enum MediumLevelILLiftedInstructionKind {
+ Nop,
+ Noret,
+ Bp,
+ Undef,
+ Unimpl,
+ If(LiftedIf),
+ FloatConst(FloatConst),
+ Const(Constant),
+ ConstPtr(Constant),
+ Import(Constant),
+ ExternPtr(ExternPtr),
+ ConstData(LiftedConstData),
+ Jump(LiftedJump),
+ RetHint(LiftedJump),
+ StoreSsa(LiftedStoreSsa),
+ StoreStructSsa(LiftedStoreStructSsa),
+ StoreStruct(LiftedStoreStruct),
+ Store(LiftedStore),
+ JumpTo(LiftedJumpTo),
+ Goto(Goto),
+ FreeVarSlot(FreeVarSlot),
+ SetVarField(LiftedSetVarField),
+ SetVar(LiftedSetVar),
+ FreeVarSlotSsa(FreeVarSlotSsa),
+ SetVarSsaField(LiftedSetVarSsaField),
+ SetVarAliasedField(LiftedSetVarSsaField),
+ SetVarAliased(LiftedSetVarAliased),
+ SetVarSsa(LiftedSetVarSsa),
+ VarPhi(LiftedVarPhi),
+ MemPhi(LiftedMemPhi),
+ VarSplit(VarSplit),
+ SetVarSplit(LiftedSetVarSplit),
+ VarSplitSsa(VarSplitSsa),
+ SetVarSplitSsa(LiftedSetVarSplitSsa),
+ Add(LiftedBinaryOp),
+ Sub(LiftedBinaryOp),
+ And(LiftedBinaryOp),
+ Or(LiftedBinaryOp),
+ Xor(LiftedBinaryOp),
+ Lsl(LiftedBinaryOp),
+ Lsr(LiftedBinaryOp),
+ Asr(LiftedBinaryOp),
+ Rol(LiftedBinaryOp),
+ Ror(LiftedBinaryOp),
+ Mul(LiftedBinaryOp),
+ MuluDp(LiftedBinaryOp),
+ MulsDp(LiftedBinaryOp),
+ Divu(LiftedBinaryOp),
+ DivuDp(LiftedBinaryOp),
+ Divs(LiftedBinaryOp),
+ DivsDp(LiftedBinaryOp),
+ Modu(LiftedBinaryOp),
+ ModuDp(LiftedBinaryOp),
+ Mods(LiftedBinaryOp),
+ ModsDp(LiftedBinaryOp),
+ CmpE(LiftedBinaryOp),
+ CmpNe(LiftedBinaryOp),
+ CmpSlt(LiftedBinaryOp),
+ CmpUlt(LiftedBinaryOp),
+ CmpSle(LiftedBinaryOp),
+ CmpUle(LiftedBinaryOp),
+ CmpSge(LiftedBinaryOp),
+ CmpUge(LiftedBinaryOp),
+ CmpSgt(LiftedBinaryOp),
+ CmpUgt(LiftedBinaryOp),
+ TestBit(LiftedBinaryOp),
+ AddOverflow(LiftedBinaryOp),
+ FcmpE(LiftedBinaryOp),
+ FcmpNe(LiftedBinaryOp),
+ FcmpLt(LiftedBinaryOp),
+ FcmpLe(LiftedBinaryOp),
+ FcmpGe(LiftedBinaryOp),
+ FcmpGt(LiftedBinaryOp),
+ FcmpO(LiftedBinaryOp),
+ FcmpUo(LiftedBinaryOp),
+ Fadd(LiftedBinaryOp),
+ Fsub(LiftedBinaryOp),
+ Fmul(LiftedBinaryOp),
+ Fdiv(LiftedBinaryOp),
+ Adc(LiftedBinaryOpCarry),
+ Sbb(LiftedBinaryOpCarry),
+ Rlc(LiftedBinaryOpCarry),
+ Rrc(LiftedBinaryOpCarry),
+ Call(LiftedCall),
+ Tailcall(LiftedCall),
+ Intrinsic(LiftedIntrinsic),
+ Syscall(LiftedSyscallCall),
+ IntrinsicSsa(LiftedIntrinsicSsa),
+ CallSsa(LiftedCallSsa),
+ TailcallSsa(LiftedCallSsa),
+ CallUntypedSsa(LiftedCallUntypedSsa),
+ TailcallUntypedSsa(LiftedCallUntypedSsa),
+ SyscallSsa(LiftedSyscallSsa),
+ SyscallUntypedSsa(LiftedSyscallUntypedSsa),
+ CallUntyped(LiftedCallUntyped),
+ TailcallUntyped(LiftedCallUntyped),
+ SyscallUntyped(LiftedSyscallUntyped),
+ SeparateParamList(LiftedSeparateParamList),
+ SharedParamSlot(LiftedSharedParamSlot),
+ Neg(LiftedUnaryOp),
+ Not(LiftedUnaryOp),
+ Sx(LiftedUnaryOp),
+ Zx(LiftedUnaryOp),
+ LowPart(LiftedUnaryOp),
+ BoolToInt(LiftedUnaryOp),
+ UnimplMem(LiftedUnaryOp),
+ Fsqrt(LiftedUnaryOp),
+ Fneg(LiftedUnaryOp),
+ Fabs(LiftedUnaryOp),
+ FloatToInt(LiftedUnaryOp),
+ IntToFloat(LiftedUnaryOp),
+ FloatConv(LiftedUnaryOp),
+ RoundToInt(LiftedUnaryOp),
+ Floor(LiftedUnaryOp),
+ Ceil(LiftedUnaryOp),
+ Ftrunc(LiftedUnaryOp),
+ Load(LiftedUnaryOp),
+ LoadStruct(LiftedLoadStruct),
+ LoadStructSsa(LiftedLoadStructSsa),
+ LoadSsa(LiftedLoadSsa),
+ Ret(LiftedRet),
+ Var(Var),
+ AddressOf(Var),
+ VarField(Field),
+ AddressOfField(Field),
+ VarSsa(VarSsa),
+ VarAliased(VarSsa),
+ VarSsaField(VarSsaField),
+ VarAliasedField(VarSsaField),
+ Trap(Trap),
+}
+
+impl MediumLevelILLiftedInstruction {
+ pub fn name(&self) -> &'static str {
+ use MediumLevelILLiftedInstructionKind::*;
+ match self.kind {
+ Nop => "Nop",
+ Noret => "Noret",
+ Bp => "Bp",
+ Undef => "Undef",
+ Unimpl => "Unimpl",
+ If(_) => "If",
+ FloatConst(_) => "FloatConst",
+ Const(_) => "Const",
+ ConstPtr(_) => "ConstPtr",
+ Import(_) => "Import",
+ ExternPtr(_) => "ExternPtr",
+ ConstData(_) => "ConstData",
+ Jump(_) => "Jump",
+ RetHint(_) => "RetHint",
+ StoreSsa(_) => "StoreSsa",
+ StoreStructSsa(_) => "StoreStructSsa",
+ StoreStruct(_) => "StoreStruct",
+ Store(_) => "Store",
+ JumpTo(_) => "JumpTo",
+ Goto(_) => "Goto",
+ FreeVarSlot(_) => "FreeVarSlot",
+ SetVarField(_) => "SetVarField",
+ SetVar(_) => "SetVar",
+ FreeVarSlotSsa(_) => "FreeVarSlotSsa",
+ SetVarSsaField(_) => "SetVarSsaField",
+ SetVarAliasedField(_) => "SetVarAliasedField",
+ SetVarAliased(_) => "SetVarAliased",
+ SetVarSsa(_) => "SetVarSsa",
+ VarPhi(_) => "VarPhi",
+ MemPhi(_) => "MemPhi",
+ VarSplit(_) => "VarSplit",
+ SetVarSplit(_) => "SetVarSplit",
+ VarSplitSsa(_) => "VarSplitSsa",
+ SetVarSplitSsa(_) => "SetVarSplitSsa",
+ Add(_) => "Add",
+ Sub(_) => "Sub",
+ And(_) => "And",
+ Or(_) => "Or",
+ Xor(_) => "Xor",
+ Lsl(_) => "Lsl",
+ Lsr(_) => "Lsr",
+ Asr(_) => "Asr",
+ Rol(_) => "Rol",
+ Ror(_) => "Ror",
+ Mul(_) => "Mul",
+ MuluDp(_) => "MuluDp",
+ MulsDp(_) => "MulsDp",
+ Divu(_) => "Divu",
+ DivuDp(_) => "DivuDp",
+ Divs(_) => "Divs",
+ DivsDp(_) => "DivsDp",
+ Modu(_) => "Modu",
+ ModuDp(_) => "ModuDp",
+ Mods(_) => "Mods",
+ ModsDp(_) => "ModsDp",
+ CmpE(_) => "CmpE",
+ CmpNe(_) => "CmpNe",
+ CmpSlt(_) => "CmpSlt",
+ CmpUlt(_) => "CmpUlt",
+ CmpSle(_) => "CmpSle",
+ CmpUle(_) => "CmpUle",
+ CmpSge(_) => "CmpSge",
+ CmpUge(_) => "CmpUge",
+ CmpSgt(_) => "CmpSgt",
+ CmpUgt(_) => "CmpUgt",
+ TestBit(_) => "TestBit",
+ AddOverflow(_) => "AddOverflow",
+ FcmpE(_) => "FcmpE",
+ FcmpNe(_) => "FcmpNe",
+ FcmpLt(_) => "FcmpLt",
+ FcmpLe(_) => "FcmpLe",
+ FcmpGe(_) => "FcmpGe",
+ FcmpGt(_) => "FcmpGt",
+ FcmpO(_) => "FcmpO",
+ FcmpUo(_) => "FcmpUo",
+ Fadd(_) => "Fadd",
+ Fsub(_) => "Fsub",
+ Fmul(_) => "Fmul",
+ Fdiv(_) => "Fdiv",
+ Adc(_) => "Adc",
+ Sbb(_) => "Sbb",
+ Rlc(_) => "Rlc",
+ Rrc(_) => "Rrc",
+ Call(_) => "Call",
+ Tailcall(_) => "Tailcall",
+ Syscall(_) => "Syscall",
+ Intrinsic(_) => "Intrinsic",
+ IntrinsicSsa(_) => "IntrinsicSsa",
+ CallSsa(_) => "CallSsa",
+ TailcallSsa(_) => "TailcallSsa",
+ CallUntypedSsa(_) => "CallUntypedSsa",
+ TailcallUntypedSsa(_) => "TailcallUntypedSsa",
+ SyscallSsa(_) => "SyscallSsa",
+ SyscallUntypedSsa(_) => "SyscallUntypedSsa",
+ CallUntyped(_) => "CallUntyped",
+ TailcallUntyped(_) => "TailcallUntyped",
+ SyscallUntyped(_) => "SyscallUntyped",
+ SeparateParamList(_) => "SeparateParamList",
+ SharedParamSlot(_) => "SharedParamSlot",
+ Neg(_) => "Neg",
+ Not(_) => "Not",
+ Sx(_) => "Sx",
+ Zx(_) => "Zx",
+ LowPart(_) => "LowPart",
+ BoolToInt(_) => "BoolToInt",
+ UnimplMem(_) => "UnimplMem",
+ Fsqrt(_) => "Fsqrt",
+ Fneg(_) => "Fneg",
+ Fabs(_) => "Fabs",
+ FloatToInt(_) => "FloatToInt",
+ IntToFloat(_) => "IntToFloat",
+ FloatConv(_) => "FloatConv",
+ RoundToInt(_) => "RoundToInt",
+ Floor(_) => "Floor",
+ Ceil(_) => "Ceil",
+ Ftrunc(_) => "Ftrunc",
+ Load(_) => "Load",
+ LoadStruct(_) => "LoadStruct",
+ LoadStructSsa(_) => "LoadStructSsa",
+ LoadSsa(_) => "LoadSsa",
+ Ret(_) => "Ret",
+ Var(_) => "Var",
+ AddressOf(_) => "AddressOf",
+ VarField(_) => "VarField",
+ AddressOfField(_) => "AddressOfField",
+ VarSsa(_) => "VarSsa",
+ VarAliased(_) => "VarAliased",
+ VarSsaField(_) => "VarSsaField",
+ VarAliasedField(_) => "VarAliasedField",
+ Trap(_) => "Trap",
+ }
+ }
+
+ pub fn operands(&self) -> Vec<(&'static str, MediumLevelILLiftedOperand)> {
+ use MediumLevelILLiftedInstructionKind::*;
+ use MediumLevelILLiftedOperand as Operand;
+ match &self.kind {
+ Nop | Noret | Bp | Undef | Unimpl => vec![],
+ If(op) => vec![
+ ("condition", Operand::Expr(*op.condition.clone())),
+ ("dest_true", Operand::InstructionIndex(op.dest_true)),
+ ("dest_false", Operand::InstructionIndex(op.dest_false)),
+ ],
+ FloatConst(op) => vec![("constant", Operand::Float(op.constant))],
+ Const(op) | ConstPtr(op) | Import(op) => vec![("constant", Operand::Int(op.constant))],
+ ExternPtr(op) => vec![
+ ("constant", Operand::Int(op.constant)),
+ ("offset", Operand::Int(op.offset)),
+ ],
+ ConstData(op) => vec![(
+ "constant_data",
+ Operand::ConstantData(op.constant_data.clone()),
+ )],
+ Jump(op) | RetHint(op) => vec![("dest", Operand::Expr(*op.dest.clone()))],
+ StoreSsa(op) => vec![
+ ("dest", Operand::Expr(*op.dest.clone())),
+ ("dest_memory", Operand::Int(op.dest_memory)),
+ ("src_memory", Operand::Int(op.src_memory)),
+ ("src", Operand::Expr(*op.src.clone())),
+ ],
+ StoreStructSsa(op) => vec![
+ ("dest", Operand::Expr(*op.dest.clone())),
+ ("offset", Operand::Int(op.offset)),
+ ("dest_memory", Operand::Int(op.dest_memory)),
+ ("src_memory", Operand::Int(op.src_memory)),
+ ("src", Operand::Expr(*op.src.clone())),
+ ],
+ StoreStruct(op) => vec![
+ ("dest", Operand::Expr(*op.dest.clone())),
+ ("offset", Operand::Int(op.offset)),
+ ("src", Operand::Expr(*op.src.clone())),
+ ],
+ Store(op) => vec![
+ ("dest", Operand::Expr(*op.dest.clone())),
+ ("src", Operand::Expr(*op.src.clone())),
+ ],
+ JumpTo(op) => vec![
+ ("dest", Operand::Expr(*op.dest.clone())),
+ ("targets", Operand::TargetMap(op.targets.clone())),
+ ],
+ Goto(op) => vec![("dest", Operand::InstructionIndex(op.dest))],
+ FreeVarSlot(op) => vec![("dest", Operand::Var(op.dest))],
+ SetVarField(op) => vec![
+ ("dest", Operand::Var(op.dest)),
+ ("offset", Operand::Int(op.offset)),
+ ("src", Operand::Expr(*op.src.clone())),
+ ],
+ SetVar(op) => vec![
+ ("dest", Operand::Var(op.dest)),
+ ("src", Operand::Expr(*op.src.clone())),
+ ],
+ FreeVarSlotSsa(op) => vec![
+ ("dest", Operand::VarSsa(op.dest)),
+ ("prev", Operand::VarSsa(op.prev)),
+ ],
+ SetVarSsaField(op) | SetVarAliasedField(op) => vec![
+ ("dest", Operand::VarSsa(op.dest)),
+ ("prev", Operand::VarSsa(op.prev)),
+ ("offset", Operand::Int(op.offset)),
+ ("src", Operand::Expr(*op.src.clone())),
+ ],
+ SetVarAliased(op) => vec![
+ ("dest", Operand::VarSsa(op.dest)),
+ ("prev", Operand::VarSsa(op.prev)),
+ ("src", Operand::Expr(*op.src.clone())),
+ ],
+ SetVarSsa(op) => vec![
+ ("dest", Operand::VarSsa(op.dest)),
+ ("src", Operand::Expr(*op.src.clone())),
+ ],
+ VarPhi(op) => vec![
+ ("dest", Operand::VarSsa(op.dest)),
+ ("src", Operand::VarSsaList(op.src.clone())),
+ ],
+ MemPhi(op) => vec![
+ ("dest_memory", Operand::Int(op.dest_memory)),
+ ("src_memory", Operand::IntList(op.src_memory.clone())),
+ ],
+ VarSplit(op) => vec![
+ ("high", Operand::Var(op.high)),
+ ("low", Operand::Var(op.low)),
+ ],
+ SetVarSplit(op) => vec![
+ ("high", Operand::Var(op.high)),
+ ("low", Operand::Var(op.low)),
+ ("src", Operand::Expr(*op.src.clone())),
+ ],
+ VarSplitSsa(op) => vec![
+ ("high", Operand::VarSsa(op.high)),
+ ("low", Operand::VarSsa(op.low)),
+ ],
+ SetVarSplitSsa(op) => vec![
+ ("high", Operand::VarSsa(op.high)),
+ ("low", Operand::VarSsa(op.low)),
+ ("src", Operand::Expr(*op.src.clone())),
+ ],
+ Add(op) | Sub(op) | And(op) | Or(op) | Xor(op) | Lsl(op) | Lsr(op) | Asr(op)
+ | Rol(op) | Ror(op) | Mul(op) | MuluDp(op) | MulsDp(op) | Divu(op) | DivuDp(op)
+ | Divs(op) | DivsDp(op) | Modu(op) | ModuDp(op) | Mods(op) | ModsDp(op) | CmpE(op)
+ | CmpNe(op) | CmpSlt(op) | CmpUlt(op) | CmpSle(op) | CmpUle(op) | CmpSge(op)
+ | CmpUge(op) | CmpSgt(op) | CmpUgt(op) | TestBit(op) | AddOverflow(op) | FcmpE(op)
+ | FcmpNe(op) | FcmpLt(op) | FcmpLe(op) | FcmpGe(op) | FcmpGt(op) | FcmpO(op)
+ | FcmpUo(op) | Fadd(op) | Fsub(op) | Fmul(op) | Fdiv(op) => vec![
+ ("left", Operand::Expr(*op.left.clone())),
+ ("right", Operand::Expr(*op.right.clone())),
+ ],
+ Adc(op) | Sbb(op) | Rlc(op) | Rrc(op) => vec![
+ ("left", Operand::Expr(*op.left.clone())),
+ ("right", Operand::Expr(*op.right.clone())),
+ ("carry", Operand::Expr(*op.carry.clone())),
+ ],
+ Call(op) | Tailcall(op) => vec![
+ ("output", Operand::VarList(op.output.clone())),
+ ("dest", Operand::Expr(*op.dest.clone())),
+ ("params", Operand::ExprList(op.params.clone())),
+ ],
+ Syscall(op) => vec![
+ ("output", Operand::VarList(op.output.clone())),
+ ("params", Operand::ExprList(op.params.clone())),
+ ],
+ Intrinsic(op) => vec![
+ ("output", Operand::VarList(op.output.clone())),
+ ("intrinsic", Operand::Intrinsic(op.intrinsic)),
+ ("params", Operand::ExprList(op.params.clone())),
+ ],
+ IntrinsicSsa(op) => vec![
+ ("output", Operand::VarSsaList(op.output.clone())),
+ ("intrinsic", Operand::Intrinsic(op.intrinsic)),
+ ("params", Operand::ExprList(op.params.clone())),
+ ],
+ CallSsa(op) | TailcallSsa(op) => vec![
+ ("output", Operand::VarSsaList(op.output.clone())),
+ ("dest", Operand::Expr(*op.dest.clone())),
+ ("params", Operand::ExprList(op.params.clone())),
+ ("src_memory", Operand::Int(op.src_memory)),
+ ],
+ CallUntypedSsa(op) | TailcallUntypedSsa(op) => vec![
+ ("output", Operand::VarSsaList(op.output.clone())),
+ ("dest", Operand::Expr(*op.dest.clone())),
+ ("params", Operand::ExprList(op.params.clone())),
+ ("stack", Operand::Expr(*op.stack.clone())),
+ ],
+ SyscallSsa(op) => vec![
+ ("output", Operand::VarSsaList(op.output.clone())),
+ ("params", Operand::ExprList(op.params.clone())),
+ ("src_memory", Operand::Int(op.src_memory)),
+ ],
+ SyscallUntypedSsa(op) => vec![
+ ("output", Operand::VarSsaList(op.output.clone())),
+ ("params", Operand::ExprList(op.params.clone())),
+ ("stack", Operand::Expr(*op.stack.clone())),
+ ],
+ CallUntyped(op) | TailcallUntyped(op) => vec![
+ ("output", Operand::VarList(op.output.clone())),
+ ("dest", Operand::Expr(*op.dest.clone())),
+ ("params", Operand::ExprList(op.params.clone())),
+ ("stack", Operand::Expr(*op.stack.clone())),
+ ],
+ SyscallUntyped(op) => vec![
+ ("output", Operand::VarList(op.output.clone())),
+ ("params", Operand::ExprList(op.params.clone())),
+ ("stack", Operand::Expr(*op.stack.clone())),
+ ],
+ Neg(op) | Not(op) | Sx(op) | Zx(op) | LowPart(op) | BoolToInt(op) | UnimplMem(op)
+ | Fsqrt(op) | Fneg(op) | Fabs(op) | FloatToInt(op) | IntToFloat(op) | FloatConv(op)
+ | RoundToInt(op) | Floor(op) | Ceil(op) | Ftrunc(op) | Load(op) => {
+ vec![("src", Operand::Expr(*op.src.clone()))]
+ }
+ LoadStruct(op) => vec![
+ ("src", Operand::Expr(*op.src.clone())),
+ ("offset", Operand::Int(op.offset)),
+ ],
+ LoadStructSsa(op) => vec![
+ ("src", Operand::Expr(*op.src.clone())),
+ ("offset", Operand::Int(op.offset)),
+ ("src_memory", Operand::Int(op.src_memory)),
+ ],
+ LoadSsa(op) => vec![
+ ("src", Operand::Expr(*op.src.clone())),
+ ("src_memory", Operand::Int(op.src_memory)),
+ ],
+ Ret(op) => vec![("src", Operand::ExprList(op.src.clone()))],
+ SeparateParamList(op) => vec![("params", Operand::ExprList(op.params.clone()))],
+ SharedParamSlot(op) => vec![("params", Operand::ExprList(op.params.clone()))],
+ Var(op) | AddressOf(op) => vec![("src", Operand::Var(op.src))],
+ VarField(op) | AddressOfField(op) => vec![
+ ("src", Operand::Var(op.src)),
+ ("offset", Operand::Int(op.offset)),
+ ],
+ VarSsa(op) | VarAliased(op) => vec![("src", Operand::VarSsa(op.src))],
+ VarSsaField(op) | VarAliasedField(op) => vec![
+ ("src", Operand::VarSsa(op.src)),
+ ("offset", Operand::Int(op.offset)),
+ ],
+ Trap(op) => vec![("vector", Operand::Int(op.vector))],
+ }
+ }
+}