/* * Copyright (C) 2019 Intel Corporation. All rights reserved. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ #include "aot_emit_compare.h" static bool int_cond_to_llvm_op(IntCond cond, LLVMIntPredicate *op) { if (cond < INT_EQZ || cond > INT_GE_U) return false; switch (cond) { case INT_EQZ: case INT_EQ: *op = LLVMIntEQ; break; case INT_NE: *op = LLVMIntNE; break; case INT_LT_S: *op = LLVMIntSLT; break; case INT_LT_U: *op = LLVMIntULT; break; case INT_GT_S: *op = LLVMIntSGT; break; case INT_GT_U: *op = LLVMIntUGT; break; case INT_LE_S: *op = LLVMIntSLE; break; case INT_LE_U: *op = LLVMIntULE; break; case INT_GE_S: *op = LLVMIntSGE; break; case INT_GE_U: *op = LLVMIntUGE; break; default: return false; } return true; } static bool float_cond_to_llvm_op(FloatCond cond, LLVMRealPredicate *op) { if (cond < FLOAT_EQ || cond > FLOAT_GE) return false; switch (cond) { case FLOAT_EQ: *op = LLVMRealOEQ; break; case FLOAT_NE: *op = LLVMRealUNE; break; case FLOAT_LT: *op = LLVMRealOLT; break; case FLOAT_GT: *op = LLVMRealOGT; break; case FLOAT_LE: *op = LLVMRealOLE; break; case FLOAT_GE: *op = LLVMRealOGE; break; default: return false; } return true; } bool aot_compile_op_i32_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, IntCond cond) { LLVMIntPredicate op; LLVMValueRef lhs, rhs, res; if (!int_cond_to_llvm_op(cond, &op)) { aot_set_last_error("invalid WASM condition opcode"); return false; } if (cond == INT_EQZ) rhs = I32_ZERO; else POP_I32(rhs); POP_I32(lhs); if (!(res = LLVMBuildICmp(comp_ctx->builder, op, lhs, rhs, "i32_cmp"))) { aot_set_last_error("llvm build compare failed."); return false; } PUSH_COND(res); return true; fail: return false; } bool aot_compile_op_i64_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, IntCond cond) { LLVMIntPredicate op; LLVMValueRef lhs, rhs, res; if (!int_cond_to_llvm_op(cond, &op)) { aot_set_last_error("invalid WASM condition opcode"); return false; } if (cond == INT_EQZ) rhs = I64_CONST(0); else POP_I64(rhs); POP_I64(lhs); if (!(res = LLVMBuildICmp(comp_ctx->builder, op, lhs, rhs, "i64_cmp"))) { aot_set_last_error("llvm build compare failed."); return false; } PUSH_COND(res); return true; fail: return false; } bool aot_compile_op_f32_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, FloatCond cond) { LLVMRealPredicate op; LLVMValueRef lhs, rhs, res; if (!float_cond_to_llvm_op(cond, &op)) { aot_set_last_error("invalid WASM condition opcode"); return false; } POP_F32(rhs); POP_F32(lhs); if (!(res = LLVMBuildFCmp(comp_ctx->builder, op, lhs, rhs, "f32_cmp"))) { aot_set_last_error("llvm build compare failed."); return false; } PUSH_COND(res); return true; fail: return false; } bool aot_compile_op_f64_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, FloatCond cond) { LLVMRealPredicate op; LLVMValueRef lhs, rhs, res; if (!float_cond_to_llvm_op(cond, &op)) { aot_set_last_error("invalid WASM condition opcode"); return false; } POP_F64(rhs); POP_F64(lhs); if (!(res = LLVMBuildFCmp(comp_ctx->builder, op, lhs, rhs, "f64_cmp"))) { aot_set_last_error("llvm build compare failed."); return false; } PUSH_COND(res); return true; fail: return false; }