brintos

brintos / llvm-project-archived public Read only

0
0
Text · 29.3 KiB · 1a1889a Raw
678 lines · cpp
1//===-- WebAssembly.cpp - Emit LLVM Code for builtins ---------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This contains code to emit Builtin calls as LLVM code.10//11//===----------------------------------------------------------------------===//12 13#include "CGBuiltin.h"14#include "clang/Basic/TargetBuiltins.h"15#include "llvm/ADT/APInt.h"16#include "llvm/IR/Constants.h"17#include "llvm/IR/IntrinsicsWebAssembly.h"18#include "llvm/Support/ErrorHandling.h"19 20using namespace clang;21using namespace CodeGen;22using namespace llvm;23 24Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,25                                                   const CallExpr *E) {26  switch (BuiltinID) {27  case WebAssembly::BI__builtin_wasm_memory_size: {28    llvm::Type *ResultType = ConvertType(E->getType());29    Value *I = EmitScalarExpr(E->getArg(0));30    Function *Callee =31        CGM.getIntrinsic(Intrinsic::wasm_memory_size, ResultType);32    return Builder.CreateCall(Callee, I);33  }34  case WebAssembly::BI__builtin_wasm_memory_grow: {35    llvm::Type *ResultType = ConvertType(E->getType());36    Value *Args[] = {EmitScalarExpr(E->getArg(0)),37                     EmitScalarExpr(E->getArg(1))};38    Function *Callee =39        CGM.getIntrinsic(Intrinsic::wasm_memory_grow, ResultType);40    return Builder.CreateCall(Callee, Args);41  }42  case WebAssembly::BI__builtin_wasm_tls_size: {43    llvm::Type *ResultType = ConvertType(E->getType());44    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_tls_size, ResultType);45    return Builder.CreateCall(Callee);46  }47  case WebAssembly::BI__builtin_wasm_tls_align: {48    llvm::Type *ResultType = ConvertType(E->getType());49    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_tls_align, ResultType);50    return Builder.CreateCall(Callee);51  }52  case WebAssembly::BI__builtin_wasm_tls_base: {53    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_tls_base);54    return Builder.CreateCall(Callee);55  }56  case WebAssembly::BI__builtin_wasm_throw: {57    Value *Tag = EmitScalarExpr(E->getArg(0));58    Value *Obj = EmitScalarExpr(E->getArg(1));59    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_throw);60    return EmitRuntimeCallOrInvoke(Callee, {Tag, Obj});61  }62  case WebAssembly::BI__builtin_wasm_rethrow: {63    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_rethrow);64    return EmitRuntimeCallOrInvoke(Callee);65  }66  case WebAssembly::BI__builtin_wasm_memory_atomic_wait32: {67    Value *Addr = EmitScalarExpr(E->getArg(0));68    Value *Expected = EmitScalarExpr(E->getArg(1));69    Value *Timeout = EmitScalarExpr(E->getArg(2));70    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_memory_atomic_wait32);71    return Builder.CreateCall(Callee, {Addr, Expected, Timeout});72  }73  case WebAssembly::BI__builtin_wasm_memory_atomic_wait64: {74    Value *Addr = EmitScalarExpr(E->getArg(0));75    Value *Expected = EmitScalarExpr(E->getArg(1));76    Value *Timeout = EmitScalarExpr(E->getArg(2));77    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_memory_atomic_wait64);78    return Builder.CreateCall(Callee, {Addr, Expected, Timeout});79  }80  case WebAssembly::BI__builtin_wasm_memory_atomic_notify: {81    Value *Addr = EmitScalarExpr(E->getArg(0));82    Value *Count = EmitScalarExpr(E->getArg(1));83    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_memory_atomic_notify);84    return Builder.CreateCall(Callee, {Addr, Count});85  }86  case WebAssembly::BI__builtin_wasm_trunc_s_i32_f32:87  case WebAssembly::BI__builtin_wasm_trunc_s_i32_f64:88  case WebAssembly::BI__builtin_wasm_trunc_s_i64_f32:89  case WebAssembly::BI__builtin_wasm_trunc_s_i64_f64: {90    Value *Src = EmitScalarExpr(E->getArg(0));91    llvm::Type *ResT = ConvertType(E->getType());92    Function *Callee =93        CGM.getIntrinsic(Intrinsic::wasm_trunc_signed, {ResT, Src->getType()});94    return Builder.CreateCall(Callee, {Src});95  }96  case WebAssembly::BI__builtin_wasm_trunc_u_i32_f32:97  case WebAssembly::BI__builtin_wasm_trunc_u_i32_f64:98  case WebAssembly::BI__builtin_wasm_trunc_u_i64_f32:99  case WebAssembly::BI__builtin_wasm_trunc_u_i64_f64: {100    Value *Src = EmitScalarExpr(E->getArg(0));101    llvm::Type *ResT = ConvertType(E->getType());102    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_trunc_unsigned,103                                        {ResT, Src->getType()});104    return Builder.CreateCall(Callee, {Src});105  }106  case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i32_f32:107  case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i32_f64:108  case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i64_f32:109  case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i64_f64:110  case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i16x8_f16x8:111  case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i32x4_f32x4: {112    Value *Src = EmitScalarExpr(E->getArg(0));113    llvm::Type *ResT = ConvertType(E->getType());114    Function *Callee =115        CGM.getIntrinsic(Intrinsic::fptosi_sat, {ResT, Src->getType()});116    return Builder.CreateCall(Callee, {Src});117  }118  case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i32_f32:119  case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i32_f64:120  case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i64_f32:121  case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i64_f64:122  case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i16x8_f16x8:123  case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i32x4_f32x4: {124    Value *Src = EmitScalarExpr(E->getArg(0));125    llvm::Type *ResT = ConvertType(E->getType());126    Function *Callee =127        CGM.getIntrinsic(Intrinsic::fptoui_sat, {ResT, Src->getType()});128    return Builder.CreateCall(Callee, {Src});129  }130  case WebAssembly::BI__builtin_wasm_min_f32:131  case WebAssembly::BI__builtin_wasm_min_f64:132  case WebAssembly::BI__builtin_wasm_min_f16x8:133  case WebAssembly::BI__builtin_wasm_min_f32x4:134  case WebAssembly::BI__builtin_wasm_min_f64x2: {135    Value *LHS = EmitScalarExpr(E->getArg(0));136    Value *RHS = EmitScalarExpr(E->getArg(1));137    Function *Callee =138        CGM.getIntrinsic(Intrinsic::minimum, ConvertType(E->getType()));139    return Builder.CreateCall(Callee, {LHS, RHS});140  }141  case WebAssembly::BI__builtin_wasm_max_f32:142  case WebAssembly::BI__builtin_wasm_max_f64:143  case WebAssembly::BI__builtin_wasm_max_f16x8:144  case WebAssembly::BI__builtin_wasm_max_f32x4:145  case WebAssembly::BI__builtin_wasm_max_f64x2: {146    Value *LHS = EmitScalarExpr(E->getArg(0));147    Value *RHS = EmitScalarExpr(E->getArg(1));148    Function *Callee =149        CGM.getIntrinsic(Intrinsic::maximum, ConvertType(E->getType()));150    return Builder.CreateCall(Callee, {LHS, RHS});151  }152  case WebAssembly::BI__builtin_wasm_pmin_f16x8:153  case WebAssembly::BI__builtin_wasm_pmin_f32x4:154  case WebAssembly::BI__builtin_wasm_pmin_f64x2: {155    Value *LHS = EmitScalarExpr(E->getArg(0));156    Value *RHS = EmitScalarExpr(E->getArg(1));157    Function *Callee =158        CGM.getIntrinsic(Intrinsic::wasm_pmin, ConvertType(E->getType()));159    return Builder.CreateCall(Callee, {LHS, RHS});160  }161  case WebAssembly::BI__builtin_wasm_pmax_f16x8:162  case WebAssembly::BI__builtin_wasm_pmax_f32x4:163  case WebAssembly::BI__builtin_wasm_pmax_f64x2: {164    Value *LHS = EmitScalarExpr(E->getArg(0));165    Value *RHS = EmitScalarExpr(E->getArg(1));166    Function *Callee =167        CGM.getIntrinsic(Intrinsic::wasm_pmax, ConvertType(E->getType()));168    return Builder.CreateCall(Callee, {LHS, RHS});169  }170  case WebAssembly::BI__builtin_wasm_ceil_f16x8:171  case WebAssembly::BI__builtin_wasm_floor_f16x8:172  case WebAssembly::BI__builtin_wasm_trunc_f16x8:173  case WebAssembly::BI__builtin_wasm_nearest_f16x8:174  case WebAssembly::BI__builtin_wasm_ceil_f32x4:175  case WebAssembly::BI__builtin_wasm_floor_f32x4:176  case WebAssembly::BI__builtin_wasm_trunc_f32x4:177  case WebAssembly::BI__builtin_wasm_nearest_f32x4:178  case WebAssembly::BI__builtin_wasm_ceil_f64x2:179  case WebAssembly::BI__builtin_wasm_floor_f64x2:180  case WebAssembly::BI__builtin_wasm_trunc_f64x2:181  case WebAssembly::BI__builtin_wasm_nearest_f64x2: {182    unsigned IntNo;183    switch (BuiltinID) {184    case WebAssembly::BI__builtin_wasm_ceil_f16x8:185    case WebAssembly::BI__builtin_wasm_ceil_f32x4:186    case WebAssembly::BI__builtin_wasm_ceil_f64x2:187      IntNo = Intrinsic::ceil;188      break;189    case WebAssembly::BI__builtin_wasm_floor_f16x8:190    case WebAssembly::BI__builtin_wasm_floor_f32x4:191    case WebAssembly::BI__builtin_wasm_floor_f64x2:192      IntNo = Intrinsic::floor;193      break;194    case WebAssembly::BI__builtin_wasm_trunc_f16x8:195    case WebAssembly::BI__builtin_wasm_trunc_f32x4:196    case WebAssembly::BI__builtin_wasm_trunc_f64x2:197      IntNo = Intrinsic::trunc;198      break;199    case WebAssembly::BI__builtin_wasm_nearest_f16x8:200    case WebAssembly::BI__builtin_wasm_nearest_f32x4:201    case WebAssembly::BI__builtin_wasm_nearest_f64x2:202      IntNo = Intrinsic::nearbyint;203      break;204    default:205      llvm_unreachable("unexpected builtin ID");206    }207    Value *Value = EmitScalarExpr(E->getArg(0));208    Function *Callee = CGM.getIntrinsic(IntNo, ConvertType(E->getType()));209    return Builder.CreateCall(Callee, Value);210  }211  case WebAssembly::BI__builtin_wasm_ref_null_extern: {212    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_ref_null_extern);213    return Builder.CreateCall(Callee);214  }215  case WebAssembly::BI__builtin_wasm_ref_is_null_extern: {216    Value *Src = EmitScalarExpr(E->getArg(0));217    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_ref_is_null_extern);218    return Builder.CreateCall(Callee, {Src});219  }220  case WebAssembly::BI__builtin_wasm_ref_null_func: {221    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_ref_null_func);222    return Builder.CreateCall(Callee);223  }224  case WebAssembly::BI__builtin_wasm_test_function_pointer_signature: {225    Value *FuncRef = EmitScalarExpr(E->getArg(0));226 227    // Get the function type from the argument's static type228    QualType ArgType = E->getArg(0)->getType();229    const PointerType *PtrTy = ArgType->getAs<PointerType>();230    assert(PtrTy && "Sema should have ensured this is a function pointer");231 232    const FunctionType *FuncTy = PtrTy->getPointeeType()->getAs<FunctionType>();233    assert(FuncTy && "Sema should have ensured this is a function pointer");234 235    // In the llvm IR, we won't have access any more to the type of the function236    // pointer so we need to insert this type information somehow. The237    // @llvm.wasm.ref.test.func takes varargs arguments whose values are unused238    // to indicate the type of the function to test for. See the test here:239    // llvm/test/CodeGen/WebAssembly/ref-test-func.ll240    //241    // The format is: first we include the return types (since this is a C242    // function pointer, there will be 0 or one of these) then a token type to243    // indicate the boundary between return types and param types, then the244    // param types.245 246    llvm::FunctionType *LLVMFuncTy =247        cast<llvm::FunctionType>(ConvertType(QualType(FuncTy, 0)));248 249    bool VarArg = LLVMFuncTy->isVarArg();250    unsigned NParams = LLVMFuncTy->getNumParams();251    std::vector<Value *> Args;252    Args.reserve(NParams + 3 + VarArg);253    // The only real argument is the FuncRef254    Args.push_back(FuncRef);255 256    // Add the type information257    llvm::Type *RetType = LLVMFuncTy->getReturnType();258    if (!RetType->isVoidTy()) {259      Args.push_back(PoisonValue::get(RetType));260    }261    // The token type indicates the boundary between return types and param262    // types.263    Args.push_back(PoisonValue::get(llvm::Type::getTokenTy(getLLVMContext())));264    for (unsigned i = 0; i < NParams; i++) {265      Args.push_back(PoisonValue::get(LLVMFuncTy->getParamType(i)));266    }267    if (VarArg) {268      Args.push_back(PoisonValue::get(Builder.getPtrTy()));269    }270    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_ref_test_func);271    return Builder.CreateCall(Callee, Args);272  }273  case WebAssembly::BI__builtin_wasm_swizzle_i8x16: {274    Value *Src = EmitScalarExpr(E->getArg(0));275    Value *Indices = EmitScalarExpr(E->getArg(1));276    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_swizzle);277    return Builder.CreateCall(Callee, {Src, Indices});278  }279  case WebAssembly::BI__builtin_wasm_abs_i8x16:280  case WebAssembly::BI__builtin_wasm_abs_i16x8:281  case WebAssembly::BI__builtin_wasm_abs_i32x4:282  case WebAssembly::BI__builtin_wasm_abs_i64x2: {283    Value *Vec = EmitScalarExpr(E->getArg(0));284    Value *Neg = Builder.CreateNeg(Vec, "neg");285    Constant *Zero = llvm::Constant::getNullValue(Vec->getType());286    Value *ICmp = Builder.CreateICmpSLT(Vec, Zero, "abscond");287    return Builder.CreateSelect(ICmp, Neg, Vec, "abs");288  }289  case WebAssembly::BI__builtin_wasm_avgr_u_i8x16:290  case WebAssembly::BI__builtin_wasm_avgr_u_i16x8: {291    Value *LHS = EmitScalarExpr(E->getArg(0));292    Value *RHS = EmitScalarExpr(E->getArg(1));293    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_avgr_unsigned,294                                        ConvertType(E->getType()));295    return Builder.CreateCall(Callee, {LHS, RHS});296  }297  case WebAssembly::BI__builtin_wasm_q15mulr_sat_s_i16x8: {298    Value *LHS = EmitScalarExpr(E->getArg(0));299    Value *RHS = EmitScalarExpr(E->getArg(1));300    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_q15mulr_sat_signed);301    return Builder.CreateCall(Callee, {LHS, RHS});302  }303  case WebAssembly::BI__builtin_wasm_extadd_pairwise_i8x16_s_i16x8:304  case WebAssembly::BI__builtin_wasm_extadd_pairwise_i8x16_u_i16x8:305  case WebAssembly::BI__builtin_wasm_extadd_pairwise_i16x8_s_i32x4:306  case WebAssembly::BI__builtin_wasm_extadd_pairwise_i16x8_u_i32x4: {307    Value *Vec = EmitScalarExpr(E->getArg(0));308    unsigned IntNo;309    switch (BuiltinID) {310    case WebAssembly::BI__builtin_wasm_extadd_pairwise_i8x16_s_i16x8:311    case WebAssembly::BI__builtin_wasm_extadd_pairwise_i16x8_s_i32x4:312      IntNo = Intrinsic::wasm_extadd_pairwise_signed;313      break;314    case WebAssembly::BI__builtin_wasm_extadd_pairwise_i8x16_u_i16x8:315    case WebAssembly::BI__builtin_wasm_extadd_pairwise_i16x8_u_i32x4:316      IntNo = Intrinsic::wasm_extadd_pairwise_unsigned;317      break;318    default:319      llvm_unreachable("unexpected builtin ID");320    }321 322    Function *Callee = CGM.getIntrinsic(IntNo, ConvertType(E->getType()));323    return Builder.CreateCall(Callee, Vec);324  }325  case WebAssembly::BI__builtin_wasm_bitselect: {326    Value *V1 = EmitScalarExpr(E->getArg(0));327    Value *V2 = EmitScalarExpr(E->getArg(1));328    Value *C = EmitScalarExpr(E->getArg(2));329    Function *Callee =330        CGM.getIntrinsic(Intrinsic::wasm_bitselect, ConvertType(E->getType()));331    return Builder.CreateCall(Callee, {V1, V2, C});332  }333  case WebAssembly::BI__builtin_wasm_dot_s_i32x4_i16x8: {334    Value *LHS = EmitScalarExpr(E->getArg(0));335    Value *RHS = EmitScalarExpr(E->getArg(1));336    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_dot);337    return Builder.CreateCall(Callee, {LHS, RHS});338  }339  case WebAssembly::BI__builtin_wasm_any_true_v128:340  case WebAssembly::BI__builtin_wasm_all_true_i8x16:341  case WebAssembly::BI__builtin_wasm_all_true_i16x8:342  case WebAssembly::BI__builtin_wasm_all_true_i32x4:343  case WebAssembly::BI__builtin_wasm_all_true_i64x2: {344    unsigned IntNo;345    switch (BuiltinID) {346    case WebAssembly::BI__builtin_wasm_any_true_v128:347      IntNo = Intrinsic::wasm_anytrue;348      break;349    case WebAssembly::BI__builtin_wasm_all_true_i8x16:350    case WebAssembly::BI__builtin_wasm_all_true_i16x8:351    case WebAssembly::BI__builtin_wasm_all_true_i32x4:352    case WebAssembly::BI__builtin_wasm_all_true_i64x2:353      IntNo = Intrinsic::wasm_alltrue;354      break;355    default:356      llvm_unreachable("unexpected builtin ID");357    }358    Value *Vec = EmitScalarExpr(E->getArg(0));359    Function *Callee = CGM.getIntrinsic(IntNo, Vec->getType());360    return Builder.CreateCall(Callee, {Vec});361  }362  case WebAssembly::BI__builtin_wasm_bitmask_i8x16:363  case WebAssembly::BI__builtin_wasm_bitmask_i16x8:364  case WebAssembly::BI__builtin_wasm_bitmask_i32x4:365  case WebAssembly::BI__builtin_wasm_bitmask_i64x2: {366    Value *Vec = EmitScalarExpr(E->getArg(0));367    Function *Callee =368        CGM.getIntrinsic(Intrinsic::wasm_bitmask, Vec->getType());369    return Builder.CreateCall(Callee, {Vec});370  }371  case WebAssembly::BI__builtin_wasm_abs_f16x8:372  case WebAssembly::BI__builtin_wasm_abs_f32x4:373  case WebAssembly::BI__builtin_wasm_abs_f64x2: {374    Value *Vec = EmitScalarExpr(E->getArg(0));375    Function *Callee = CGM.getIntrinsic(Intrinsic::fabs, Vec->getType());376    return Builder.CreateCall(Callee, {Vec});377  }378  case WebAssembly::BI__builtin_wasm_sqrt_f16x8:379  case WebAssembly::BI__builtin_wasm_sqrt_f32x4:380  case WebAssembly::BI__builtin_wasm_sqrt_f64x2: {381    Value *Vec = EmitScalarExpr(E->getArg(0));382    Function *Callee = CGM.getIntrinsic(Intrinsic::sqrt, Vec->getType());383    return Builder.CreateCall(Callee, {Vec});384  }385  case WebAssembly::BI__builtin_wasm_narrow_s_i8x16_i16x8:386  case WebAssembly::BI__builtin_wasm_narrow_u_i8x16_i16x8:387  case WebAssembly::BI__builtin_wasm_narrow_s_i16x8_i32x4:388  case WebAssembly::BI__builtin_wasm_narrow_u_i16x8_i32x4: {389    Value *Low = EmitScalarExpr(E->getArg(0));390    Value *High = EmitScalarExpr(E->getArg(1));391    unsigned IntNo;392    switch (BuiltinID) {393    case WebAssembly::BI__builtin_wasm_narrow_s_i8x16_i16x8:394    case WebAssembly::BI__builtin_wasm_narrow_s_i16x8_i32x4:395      IntNo = Intrinsic::wasm_narrow_signed;396      break;397    case WebAssembly::BI__builtin_wasm_narrow_u_i8x16_i16x8:398    case WebAssembly::BI__builtin_wasm_narrow_u_i16x8_i32x4:399      IntNo = Intrinsic::wasm_narrow_unsigned;400      break;401    default:402      llvm_unreachable("unexpected builtin ID");403    }404    Function *Callee =405        CGM.getIntrinsic(IntNo, {ConvertType(E->getType()), Low->getType()});406    return Builder.CreateCall(Callee, {Low, High});407  }408  case WebAssembly::BI__builtin_wasm_trunc_sat_s_zero_f64x2_i32x4:409  case WebAssembly::BI__builtin_wasm_trunc_sat_u_zero_f64x2_i32x4: {410    Value *Vec = EmitScalarExpr(E->getArg(0));411    unsigned IntNo;412    switch (BuiltinID) {413    case WebAssembly::BI__builtin_wasm_trunc_sat_s_zero_f64x2_i32x4:414      IntNo = Intrinsic::fptosi_sat;415      break;416    case WebAssembly::BI__builtin_wasm_trunc_sat_u_zero_f64x2_i32x4:417      IntNo = Intrinsic::fptoui_sat;418      break;419    default:420      llvm_unreachable("unexpected builtin ID");421    }422    llvm::Type *SrcT = Vec->getType();423    llvm::Type *TruncT = SrcT->getWithNewType(Builder.getInt32Ty());424    Function *Callee = CGM.getIntrinsic(IntNo, {TruncT, SrcT});425    Value *Trunc = Builder.CreateCall(Callee, Vec);426    Value *Splat = Constant::getNullValue(TruncT);427    return Builder.CreateShuffleVector(Trunc, Splat, {0, 1, 2, 3});428  }429  case WebAssembly::BI__builtin_wasm_shuffle_i8x16: {430    Value *Ops[18];431    size_t OpIdx = 0;432    Ops[OpIdx++] = EmitScalarExpr(E->getArg(0));433    Ops[OpIdx++] = EmitScalarExpr(E->getArg(1));434    while (OpIdx < 18) {435      std::optional<llvm::APSInt> LaneConst =436          E->getArg(OpIdx)->getIntegerConstantExpr(getContext());437      assert(LaneConst && "Constant arg isn't actually constant?");438      Ops[OpIdx++] = llvm::ConstantInt::get(getLLVMContext(), *LaneConst);439    }440    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_shuffle);441    return Builder.CreateCall(Callee, Ops);442  }443  case WebAssembly::BI__builtin_wasm_relaxed_madd_f16x8:444  case WebAssembly::BI__builtin_wasm_relaxed_nmadd_f16x8:445  case WebAssembly::BI__builtin_wasm_relaxed_madd_f32x4:446  case WebAssembly::BI__builtin_wasm_relaxed_nmadd_f32x4:447  case WebAssembly::BI__builtin_wasm_relaxed_madd_f64x2:448  case WebAssembly::BI__builtin_wasm_relaxed_nmadd_f64x2: {449    Value *A = EmitScalarExpr(E->getArg(0));450    Value *B = EmitScalarExpr(E->getArg(1));451    Value *C = EmitScalarExpr(E->getArg(2));452    unsigned IntNo;453    switch (BuiltinID) {454    case WebAssembly::BI__builtin_wasm_relaxed_madd_f16x8:455    case WebAssembly::BI__builtin_wasm_relaxed_madd_f32x4:456    case WebAssembly::BI__builtin_wasm_relaxed_madd_f64x2:457      IntNo = Intrinsic::wasm_relaxed_madd;458      break;459    case WebAssembly::BI__builtin_wasm_relaxed_nmadd_f16x8:460    case WebAssembly::BI__builtin_wasm_relaxed_nmadd_f32x4:461    case WebAssembly::BI__builtin_wasm_relaxed_nmadd_f64x2:462      IntNo = Intrinsic::wasm_relaxed_nmadd;463      break;464    default:465      llvm_unreachable("unexpected builtin ID");466    }467    Function *Callee = CGM.getIntrinsic(IntNo, A->getType());468    return Builder.CreateCall(Callee, {A, B, C});469  }470  case WebAssembly::BI__builtin_wasm_relaxed_laneselect_i8x16:471  case WebAssembly::BI__builtin_wasm_relaxed_laneselect_i16x8:472  case WebAssembly::BI__builtin_wasm_relaxed_laneselect_i32x4:473  case WebAssembly::BI__builtin_wasm_relaxed_laneselect_i64x2: {474    Value *A = EmitScalarExpr(E->getArg(0));475    Value *B = EmitScalarExpr(E->getArg(1));476    Value *C = EmitScalarExpr(E->getArg(2));477    Function *Callee =478        CGM.getIntrinsic(Intrinsic::wasm_relaxed_laneselect, A->getType());479    return Builder.CreateCall(Callee, {A, B, C});480  }481  case WebAssembly::BI__builtin_wasm_relaxed_swizzle_i8x16: {482    Value *Src = EmitScalarExpr(E->getArg(0));483    Value *Indices = EmitScalarExpr(E->getArg(1));484    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_relaxed_swizzle);485    return Builder.CreateCall(Callee, {Src, Indices});486  }487  case WebAssembly::BI__builtin_wasm_relaxed_min_f32x4:488  case WebAssembly::BI__builtin_wasm_relaxed_max_f32x4:489  case WebAssembly::BI__builtin_wasm_relaxed_min_f64x2:490  case WebAssembly::BI__builtin_wasm_relaxed_max_f64x2: {491    Value *LHS = EmitScalarExpr(E->getArg(0));492    Value *RHS = EmitScalarExpr(E->getArg(1));493    unsigned IntNo;494    switch (BuiltinID) {495    case WebAssembly::BI__builtin_wasm_relaxed_min_f32x4:496    case WebAssembly::BI__builtin_wasm_relaxed_min_f64x2:497      IntNo = Intrinsic::wasm_relaxed_min;498      break;499    case WebAssembly::BI__builtin_wasm_relaxed_max_f32x4:500    case WebAssembly::BI__builtin_wasm_relaxed_max_f64x2:501      IntNo = Intrinsic::wasm_relaxed_max;502      break;503    default:504      llvm_unreachable("unexpected builtin ID");505    }506    Function *Callee = CGM.getIntrinsic(IntNo, LHS->getType());507    return Builder.CreateCall(Callee, {LHS, RHS});508  }509  case WebAssembly::BI__builtin_wasm_relaxed_trunc_s_i32x4_f32x4:510  case WebAssembly::BI__builtin_wasm_relaxed_trunc_u_i32x4_f32x4:511  case WebAssembly::BI__builtin_wasm_relaxed_trunc_s_zero_i32x4_f64x2:512  case WebAssembly::BI__builtin_wasm_relaxed_trunc_u_zero_i32x4_f64x2: {513    Value *Vec = EmitScalarExpr(E->getArg(0));514    unsigned IntNo;515    switch (BuiltinID) {516    case WebAssembly::BI__builtin_wasm_relaxed_trunc_s_i32x4_f32x4:517      IntNo = Intrinsic::wasm_relaxed_trunc_signed;518      break;519    case WebAssembly::BI__builtin_wasm_relaxed_trunc_u_i32x4_f32x4:520      IntNo = Intrinsic::wasm_relaxed_trunc_unsigned;521      break;522    case WebAssembly::BI__builtin_wasm_relaxed_trunc_s_zero_i32x4_f64x2:523      IntNo = Intrinsic::wasm_relaxed_trunc_signed_zero;524      break;525    case WebAssembly::BI__builtin_wasm_relaxed_trunc_u_zero_i32x4_f64x2:526      IntNo = Intrinsic::wasm_relaxed_trunc_unsigned_zero;527      break;528    default:529      llvm_unreachable("unexpected builtin ID");530    }531    Function *Callee = CGM.getIntrinsic(IntNo);532    return Builder.CreateCall(Callee, {Vec});533  }534  case WebAssembly::BI__builtin_wasm_relaxed_q15mulr_s_i16x8: {535    Value *LHS = EmitScalarExpr(E->getArg(0));536    Value *RHS = EmitScalarExpr(E->getArg(1));537    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_relaxed_q15mulr_signed);538    return Builder.CreateCall(Callee, {LHS, RHS});539  }540  case WebAssembly::BI__builtin_wasm_relaxed_dot_i8x16_i7x16_s_i16x8: {541    Value *LHS = EmitScalarExpr(E->getArg(0));542    Value *RHS = EmitScalarExpr(E->getArg(1));543    Function *Callee =544        CGM.getIntrinsic(Intrinsic::wasm_relaxed_dot_i8x16_i7x16_signed);545    return Builder.CreateCall(Callee, {LHS, RHS});546  }547  case WebAssembly::BI__builtin_wasm_relaxed_dot_i8x16_i7x16_add_s_i32x4: {548    Value *LHS = EmitScalarExpr(E->getArg(0));549    Value *RHS = EmitScalarExpr(E->getArg(1));550    Value *Acc = EmitScalarExpr(E->getArg(2));551    Function *Callee =552        CGM.getIntrinsic(Intrinsic::wasm_relaxed_dot_i8x16_i7x16_add_signed);553    return Builder.CreateCall(Callee, {LHS, RHS, Acc});554  }555  case WebAssembly::BI__builtin_wasm_relaxed_dot_bf16x8_add_f32_f32x4: {556    Value *LHS = EmitScalarExpr(E->getArg(0));557    Value *RHS = EmitScalarExpr(E->getArg(1));558    Value *Acc = EmitScalarExpr(E->getArg(2));559    Function *Callee =560        CGM.getIntrinsic(Intrinsic::wasm_relaxed_dot_bf16x8_add_f32);561    return Builder.CreateCall(Callee, {LHS, RHS, Acc});562  }563  case WebAssembly::BI__builtin_wasm_loadf16_f32: {564    Value *Addr = EmitScalarExpr(E->getArg(0));565    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_loadf16_f32);566    return Builder.CreateCall(Callee, {Addr});567  }568  case WebAssembly::BI__builtin_wasm_storef16_f32: {569    Value *Val = EmitScalarExpr(E->getArg(0));570    Value *Addr = EmitScalarExpr(E->getArg(1));571    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_storef16_f32);572    return Builder.CreateCall(Callee, {Val, Addr});573  }574  case WebAssembly::BI__builtin_wasm_splat_f16x8: {575    Value *Val = EmitScalarExpr(E->getArg(0));576    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_splat_f16x8);577    return Builder.CreateCall(Callee, {Val});578  }579  case WebAssembly::BI__builtin_wasm_extract_lane_f16x8: {580    Value *Vector = EmitScalarExpr(E->getArg(0));581    Value *Index = EmitScalarExpr(E->getArg(1));582    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_extract_lane_f16x8);583    return Builder.CreateCall(Callee, {Vector, Index});584  }585  case WebAssembly::BI__builtin_wasm_replace_lane_f16x8: {586    Value *Vector = EmitScalarExpr(E->getArg(0));587    Value *Index = EmitScalarExpr(E->getArg(1));588    Value *Val = EmitScalarExpr(E->getArg(2));589    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_replace_lane_f16x8);590    return Builder.CreateCall(Callee, {Vector, Index, Val});591  }592  case WebAssembly::BI__builtin_wasm_table_get: {593    assert(E->getArg(0)->getType()->isArrayType());594    Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this);595    Value *Index = EmitScalarExpr(E->getArg(1));596    Function *Callee;597    if (E->getType().isWebAssemblyExternrefType())598      Callee = CGM.getIntrinsic(Intrinsic::wasm_table_get_externref);599    else if (E->getType().isWebAssemblyFuncrefType())600      Callee = CGM.getIntrinsic(Intrinsic::wasm_table_get_funcref);601    else602      llvm_unreachable(603          "Unexpected reference type for __builtin_wasm_table_get");604    return Builder.CreateCall(Callee, {Table, Index});605  }606  case WebAssembly::BI__builtin_wasm_table_set: {607    assert(E->getArg(0)->getType()->isArrayType());608    Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this);609    Value *Index = EmitScalarExpr(E->getArg(1));610    Value *Val = EmitScalarExpr(E->getArg(2));611    Function *Callee;612    if (E->getArg(2)->getType().isWebAssemblyExternrefType())613      Callee = CGM.getIntrinsic(Intrinsic::wasm_table_set_externref);614    else if (E->getArg(2)->getType().isWebAssemblyFuncrefType())615      Callee = CGM.getIntrinsic(Intrinsic::wasm_table_set_funcref);616    else617      llvm_unreachable(618          "Unexpected reference type for __builtin_wasm_table_set");619    return Builder.CreateCall(Callee, {Table, Index, Val});620  }621  case WebAssembly::BI__builtin_wasm_table_size: {622    assert(E->getArg(0)->getType()->isArrayType());623    Value *Value = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this);624    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_table_size);625    return Builder.CreateCall(Callee, Value);626  }627  case WebAssembly::BI__builtin_wasm_table_grow: {628    assert(E->getArg(0)->getType()->isArrayType());629    Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this);630    Value *Val = EmitScalarExpr(E->getArg(1));631    Value *NElems = EmitScalarExpr(E->getArg(2));632 633    Function *Callee;634    if (E->getArg(1)->getType().isWebAssemblyExternrefType())635      Callee = CGM.getIntrinsic(Intrinsic::wasm_table_grow_externref);636    else if (E->getArg(2)->getType().isWebAssemblyFuncrefType())637      Callee = CGM.getIntrinsic(Intrinsic::wasm_table_fill_funcref);638    else639      llvm_unreachable(640          "Unexpected reference type for __builtin_wasm_table_grow");641 642    return Builder.CreateCall(Callee, {Table, Val, NElems});643  }644  case WebAssembly::BI__builtin_wasm_table_fill: {645    assert(E->getArg(0)->getType()->isArrayType());646    Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this);647    Value *Index = EmitScalarExpr(E->getArg(1));648    Value *Val = EmitScalarExpr(E->getArg(2));649    Value *NElems = EmitScalarExpr(E->getArg(3));650 651    Function *Callee;652    if (E->getArg(2)->getType().isWebAssemblyExternrefType())653      Callee = CGM.getIntrinsic(Intrinsic::wasm_table_fill_externref);654    else if (E->getArg(2)->getType().isWebAssemblyFuncrefType())655      Callee = CGM.getIntrinsic(Intrinsic::wasm_table_fill_funcref);656    else657      llvm_unreachable(658          "Unexpected reference type for __builtin_wasm_table_fill");659 660    return Builder.CreateCall(Callee, {Table, Index, Val, NElems});661  }662  case WebAssembly::BI__builtin_wasm_table_copy: {663    assert(E->getArg(0)->getType()->isArrayType());664    Value *TableX = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this);665    Value *TableY = EmitArrayToPointerDecay(E->getArg(1)).emitRawPointer(*this);666    Value *DstIdx = EmitScalarExpr(E->getArg(2));667    Value *SrcIdx = EmitScalarExpr(E->getArg(3));668    Value *NElems = EmitScalarExpr(E->getArg(4));669 670    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_table_copy);671 672    return Builder.CreateCall(Callee, {TableX, TableY, SrcIdx, DstIdx, NElems});673  }674  default:675    return nullptr;676  }677}678