// http://llvm.org/docs/LangRef.html#extractelement-instr
// keywords: vector; instr

.type ExtractElementInstruction <: symbol
.decl extractelement_instr(instr:ExtractElementInstruction)

instr(v) :- extractelement_instr(v).

.decl extractelement_instr_base(instr:ExtractElementInstruction, vector:Operand)
.decl extractelement_instr_index(instr:ExtractElementInstruction, index:Operand)
.decl extractelement_instr_type(instr:ExtractElementInstruction, type:Type)

// The type of the elements that the vector comprises.
extractelement_instr_type(Instr, Type) :-
   extractelement_instr_base(Instr, Vector),
   operand_has_type(Vector, VectorType),
   vector_type_has_component(VectorType, Type).


//------------------------------------------------------------------------------
// [Constraints]
//
// The ‘extractelement‘ instr takes two operands:
//    (i)  the first operand is a value of vector type
//    (ii) and the second operand is an index of i32-integer type.
//
// The result is a scalar of the same type as the component type
// of the vector value.
//------------------------------------------------------------------------------

schema_invalid_instr(Instr, __FILE__, __LINE__) :-
   schema_sanity(),
   extractelement_instr(Instr),
   !extractelement_instr_base(Instr, _).

schema_invalid_instr(Instr, __FILE__, __LINE__) :-
   schema_sanity(),
   extractelement_instr(Instr),
   !extractelement_instr_index(Instr, _).

schema_invalid_instr(Instr, __FILE__, __LINE__) :-
   schema_sanity(),
   extractelement_instr(Instr),
   extractelement_instr_base(Instr, Vector),
   operand_has_type(Vector, Type),
   !vector_type(Type).

schema_invalid_instr(Instr, __FILE__, __LINE__) :-
   schema_sanity(),
   extractelement_instr(Instr),
   extractelement_instr_index(Instr, Index),
   operand_has_type(Index, Type),
   !int32_type(Type).

schema_invalid_instr(Instr, __FILE__, __LINE__) :-
   schema_sanity(),
   extractelement_instr_type(Instr, Type),
   !instr_returns_type(Instr, Type).
