Slide 106
Slide 106 text
namespace node {!
class minus : public boost::static_visitor< expression >
{!
public:!
minus(!
const std::shared_ptr< llvm::LLVMContext > &context_,!
const std::shared_ptr< ir_builder_t > &ir_builder_,!
const expression &left_, const expression &right_!
) : context( context_ ), ir_builder( ir_builder_ ),
left( left_ ), right( right_ ) {}!
template< typename Left, typename Right >!
expression operator()(!
const Left &, const Right &,!
typename boost::enable_if,!
type_traits::meta::is_arithmetic_convertible!
>!
>::type* = 0!
) const {!
const auto result_type =!
type_traits::usual_arithmetic_conversion(!
left.type(), right.type()!
);!
const expression converted_left = implicit_cast(!
context, ir_builder, result_type, left!
);!
const expression converted_right = implicit_cast(!
context, ir_builder, result_type, right!
);!
const auto llvm_type = get_llvm_type(!
context, result_type!
);!
const std::shared_ptr< llvm::LLVMContext > &context_
=!
context;!
if( type_traits::is_floating_point( result_type ) ) {!
return expression(!
result_type, llvm_type,!
std::shared_ptr< llvm::Value >(!
ir_builder->CreateFSub(!
converted_left.llvm_value().get(),!
converted_right.llvm_value().get()!
),!
[context_]( llvm::Value* ){}!
)!
);!
}!
else {!
return expression(!
result_type, llvm_type,!
std::shared_ptr< llvm::Value >(!
ir_builder->CreateSub(!
converted_left.llvm_value().get(),!
converted_right.llvm_value().get()!
),!
[context_]( llvm::Value* ){}!
)!
);!
}!
}!
template< typename Left, typename Right >!
expression operator()(!
const Left &, const Right &,!
typename boost::enable_if,!
type_traits::meta::is_arithmetic_convertible!
>!
>::type* = 0!
) const {!
const expression converted_index = implicit_cast(!
context, ir_builder,!
type_traits::integral_promotion( right.type() ),!
right!
);!
const auto pointer_type = type_traits::remove_const(!
left.type()!
);!
const auto llvm_type = get_llvm_type(!
context, pointer_type!
);!
const std::shared_ptr< llvm::LLVMContext > &context_
=!
context;!
return expression(!
pointer_type, llvm_type,!
std::shared_ptr< llvm::Value >(!
ir_builder->CreateInBoundsGEP(!
left.llvm_value().get(),!
ir_builder->CreateNeg(!
converted_index.llvm_value().get()!
)!
),!
[context_]( llvm::Value* ){}!
)!
);!
}!
template< typename Left, typename Right >!
expression operator()(!
const Left &, const Right &,!
typename boost::enable_if,!
type_traits::meta::is_arithmetic_convertible!
>,!
boost::mpl::and_,!
type_traits::meta::is_arithmetic_convertible!
>!
>!
>!
>::type* = 0!
) const {!
throw exceptions::invalid_expression();!
}!
private:!
std::shared_ptr< llvm::LLVMContext > context;!
std::shared_ptr< ir_builder_t > ir_builder;!
expression left;!
expression right;!
};!
}!
expression minus(!
const std::shared_ptr< llvm::LLVMContext > &context,!
const std::shared_ptr< ir_builder_t > &ir_builder,!
const expression &left_expr,!
const expression &right_expr!
) {!
const expression left = remove_reference(!
context, ir_builder, left_expr!
);!
const expression right = remove_reference(!
context, ir_builder, right_expr!
);!
return apply_visitor(!
node::minus( context, ir_builder, left, right ),!
left.type(), right.type()!
);!
EMBNCEBTSDDPNQJMFNJOVTDQQ