// http://llvm.org/docs/LangRef.html#trunc-to-instr
// keywords: conversion; unary; instr

.type TruncInstruction <: symbol
.decl trunc_instr(instr:TruncInstruction)

instr(v) :- trunc_instr(v).

.decl trunc_instr_from_operand(instr:TruncInstruction, val:Operand)
.decl trunc_instr_to_type(instr:TruncInstruction, type:Type)


// Helper predicate

.decl trunc_instr_from_type(instr:TruncInstruction, type:Type)

trunc_instr_from_type(Instr, Type) :-
   trunc_instr_from_operand(Instr, Operand),
   operand_has_type(Operand, Type).


//------------------------------------------------------------------------------
// [Constraints]
//
// 1) The ‘trunc‘ instr takes:
//      (i)  a value to trunc,
//      (ii) and a type to trunc it to.
//
// 2) Both source and destination types must be:
//      (i)  integers or
//      (ii) vectors of the same number of integers.
//
// 3) The source type must be larger than the destination type.
//------------------------------------------------------------------------------

schema_invalid_instr(Instr, __FILE__, __LINE__) :-
   schema_sanity(),
   trunc_instr(Instr),
   !trunc_instr_from_operand(Instr, _).

schema_invalid_instr(Instr, __FILE__, __LINE__) :-
   schema_sanity(),
   trunc_instr(Instr),
   !trunc_instr_to_type(Instr, _).

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

schema_invalid_instr(Instr, __FILE__, __LINE__) :-
   schema_sanity(),
   trunc_instr(Instr),
   trunc_instr_from_type(Instr, Type),
   !integer_type(Type),
   !integer_vector_type(Type).

schema_invalid_instr(Instr, __FILE__, __LINE__) :-
   schema_sanity(),
   trunc_instr(Instr),
   trunc_instr_to_type(Instr, Type),
   !integer_type(Type),
   !integer_vector_type(Type).

schema_invalid_instr(Instr, __FILE__, __LINE__) :-
   schema_sanity(),
   trunc_instr(Instr),
   trunc_instr_from_type(Instr, FromType),
   trunc_instr_to_type(Instr, ToType),
   !vector_compatible_types(FromType, ToType).
