| 
12 | 12 | 
 
  | 
13 | 13 | #include "CGBuiltin.h"  | 
14 | 14 | #include "clang/Basic/TargetBuiltins.h"  | 
 | 15 | +#include "llvm/ADT/APInt.h"  | 
 | 16 | +#include "llvm/IR/Constants.h"  | 
15 | 17 | #include "llvm/IR/IntrinsicsWebAssembly.h"  | 
 | 18 | +#include "llvm/Support/ErrorHandling.h"  | 
16 | 19 | 
 
  | 
17 | 20 | using namespace clang;  | 
18 | 21 | using namespace CodeGen;  | 
@@ -218,6 +221,64 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,  | 
218 | 221 |     Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_ref_null_func);  | 
219 | 222 |     return Builder.CreateCall(Callee);  | 
220 | 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 type  | 
 | 228 | +    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 function  | 
 | 236 | +    // pointer so we need to insert this type information somehow. The  | 
 | 237 | +    // @llvm.wasm.ref.test.func takes varargs arguments whose values are unused  | 
 | 238 | +    // to indicate the type of the function to test for. See the test here:  | 
 | 239 | +    // llvm/test/CodeGen/WebAssembly/ref-test-func.ll  | 
 | 240 | +    //  | 
 | 241 | +    // The format is: first we include the return types (since this is a C  | 
 | 242 | +    // function pointer, there will be 0 or one of these) then a token type to  | 
 | 243 | +    // indicate the boundary between return types and param types, then the  | 
 | 244 | +    // param types.  | 
 | 245 | + | 
 | 246 | +    llvm::FunctionType *LLVMFuncTy =  | 
 | 247 | +        cast<llvm::FunctionType>(ConvertType(QualType(FuncTy, 0)));  | 
 | 248 | + | 
 | 249 | +    unsigned NParams = LLVMFuncTy->getNumParams();  | 
 | 250 | +    std::vector<Value *> Args;  | 
 | 251 | +    Args.reserve(NParams + 3);  | 
 | 252 | +    // The only real argument is the FuncRef  | 
 | 253 | +    Args.push_back(FuncRef);  | 
 | 254 | + | 
 | 255 | +    // Add the type information  | 
 | 256 | +    auto addType = [this, &Args](llvm::Type *T) {  | 
 | 257 | +      if (T->isVoidTy()) {  | 
 | 258 | +        // Do nothing  | 
 | 259 | +      } else if (T->isFloatingPointTy()) {  | 
 | 260 | +        Args.push_back(ConstantFP::get(T, 0));  | 
 | 261 | +      } else if (T->isIntegerTy()) {  | 
 | 262 | +        Args.push_back(ConstantInt::get(T, 0));  | 
 | 263 | +      } else if (T->isPointerTy()) {  | 
 | 264 | +        Args.push_back(ConstantPointerNull::get(llvm::PointerType::get(  | 
 | 265 | +            getLLVMContext(), T->getPointerAddressSpace())));  | 
 | 266 | +      } else {  | 
 | 267 | +        // TODO: Handle reference types. For now, we reject them in Sema.  | 
 | 268 | +        llvm_unreachable("Unhandled type");  | 
 | 269 | +      }  | 
 | 270 | +    };  | 
 | 271 | + | 
 | 272 | +    addType(LLVMFuncTy->getReturnType());  | 
 | 273 | +    // The token type indicates the boundary between return types and param  | 
 | 274 | +    // types.  | 
 | 275 | +    Args.push_back(PoisonValue::get(llvm::Type::getTokenTy(getLLVMContext())));  | 
 | 276 | +    for (unsigned i = 0; i < NParams; i++) {  | 
 | 277 | +      addType(LLVMFuncTy->getParamType(i));  | 
 | 278 | +    }  | 
 | 279 | +    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_ref_test_func);  | 
 | 280 | +    return Builder.CreateCall(Callee, Args);  | 
 | 281 | +  }  | 
221 | 282 |   case WebAssembly::BI__builtin_wasm_swizzle_i8x16: {  | 
222 | 283 |     Value *Src = EmitScalarExpr(E->getArg(0));  | 
223 | 284 |     Value *Indices = EmitScalarExpr(E->getArg(1));  | 
 | 
0 commit comments