static llvm::Value* HandleTypeCastsFromIntegers(llvm::Value* value, int src_type_bw, llvm::Type* dest_type, bool sign, llvm::IRBuilder<>& builder) { llvm::Type::TypeID dest_type_id = dest_type->getTypeID(); switch (dest_type_id) { case llvm::Type::IntegerTyID: // We should never come here... return HandleIntegerTypeCast(value, dest_type, src_type_bw, dest_type->getIntegerBitWidth(), sign, builder); break; case llvm::Type::FloatTyID: // Not sure if this is required but if it does not fit in 32-bit, // go to double first. if (src_type_bw != 32) { value = HandleTypeCastsFromIntegers(value, src_type_bw, llvm::Type::getDoubleTy(llvm::getGlobalContext()), sign, builder); return HandleTypeCastsFromDoubles(value, dest_type, sign, builder); } if (sign == true) { return builder.CreateSIToFP(value, dest_type, "sitofp"); } else { return builder.CreateUIToFP(value, dest_type, "uitofp"); } case llvm::Type::DoubleTyID: if (sign == true) { return builder.CreateSIToFP(value, dest_type, "sitofp"); } else { return builder.CreateUIToFP(value, dest_type, "uitofp"); } default: assert(0); } return nullptr; }
static llvm::Value* HandleTypeCastsFromDoubles(llvm::Value* value, llvm::Type* dest_type, bool sign, llvm::IRBuilder<>& builder) { llvm::Type::TypeID dest_type_id = dest_type->getTypeID(); switch (dest_type_id) { case llvm::Type::IntegerTyID: { // Let us check we have the right size though. int dest_type_bw = dest_type->getIntegerBitWidth(); if (sign) { value = builder.CreateFPToSI(value, dest_type, "fptosi"); } else { value = builder.CreateFPToUI(value, dest_type, "fptoui"); } if (dest_type_bw != 64) { // Now go to the right size. value = HandleIntegerTypeCast(value, dest_type, 64, 32, sign, builder); } return value; } case llvm::Type::FloatTyID: return builder.CreateFPTrunc(value, dest_type, "fptrunc"); default: assert(0); } return nullptr; }
llvm::Value* MemoryExpression::GetPointer(WasmFunction*fct, llvm::IRBuilder<>& builder) const { llvm::Type* ptr_type= nullptr; if (type_ == INT_32 || type_ == INT_64) { switch (size_) { case 8: ptr_type= llvm::Type::getInt8PtrTy(llvm::getGlobalContext()); break; case 16: ptr_type= llvm::Type::getInt16PtrTy(llvm::getGlobalContext()); break; case 32: ptr_type= llvm::Type::getInt32PtrTy(llvm::getGlobalContext()); break; case 64: ptr_type= llvm::Type::getInt64PtrTy(llvm::getGlobalContext()); break; default: assert(0); break; } } else { switch (size_) { case 32: ptr_type= llvm::Type::getFloatPtrTy(llvm::getGlobalContext()); break; case 64: ptr_type= llvm::Type::getDoublePtrTy(llvm::getGlobalContext()); break; default: assert(0); break; } } assert(ptr_type != nullptr); // Create the base address in the same right type. llvm::Type* dest_type = ConvertType(type_); llvm::Value* address_i = address_->Codegen(fct, builder); llvm::Value* local_base = fct->GetLocalBase(); llvm::Type* type_64 = llvm::Type::getInt64Ty(llvm::getGlobalContext()); local_base = builder.CreatePtrToInt(local_base, type_64, "base"); llvm::Type* address_type = address_i->getType(); assert(address_type->isIntegerTy() == true); int bw = address_i->getType()->getIntegerBitWidth(); // If not 64, transform it into 64. if (bw != 64) { address_i = HandleIntegerTypeCast(address_i, type_64, bw, 64, false, builder); } address_i = builder.CreateAdd(address_i, local_base, "add_with_offset"); return builder.CreateIntToPtr(address_i, ptr_type, "ptr"); }
llvm::Value* Store::ResizeIntegerIfNeed(llvm::Value* value, llvm::Type* value_type, llvm::Type* address_type, bool sign, llvm::IRBuilder<>& builder) { // Get size differences. int value_type_bw = value_type->getIntegerBitWidth(); if (value_type_bw != size_) { // Then it depends on sign. value = HandleIntegerTypeCast(value, GetAddressType(), value_type_bw, size_, sign, builder); } return value; }
llvm::Value* HandleTypeCasts(llvm::Value* value, llvm::Type* src_type, llvm::Type* dest_type, bool sign, llvm::IRBuilder<>& builder) { if (dest_type != src_type) { llvm::Type::TypeID src_type_id = src_type->getTypeID(); switch (src_type_id) { case llvm::Type::IntegerTyID: { int src_type_bw = src_type->getIntegerBitWidth(); return HandleTypeCastsFromIntegers(value, src_type_bw, dest_type, sign, builder); } case llvm::Type::FloatTyID: return HandleTypeCastsFromFloats(value, dest_type, sign, builder); case llvm::Type::DoubleTyID: return HandleTypeCastsFromDoubles(value, dest_type, sign, builder); case llvm::Type::PointerTyID: // Probably not good to do this. return value; default: { llvm::Type::TypeID dest_type_id = dest_type->getTypeID(); BISON_PRINT("HandleTypeCast failure: destination is %d and src is %d\n", dest_type_id, src_type_id); (void) dest_type_id; assert(0); break; } } } else { // A bit more code to handle integer case llvm::Type::TypeID dest_type_id = dest_type->getTypeID(); if (dest_type_id == llvm::Type::IntegerTyID) { // Now check sizes. int dest_type_bw = dest_type->getIntegerBitWidth(); int src_type_bw = src_type->getIntegerBitWidth(); // We have a problem here. if (dest_type_bw != src_type_bw) { // Handle difference of sizes. value = HandleIntegerTypeCast(value, dest_type, src_type_bw, dest_type_bw, sign, builder); } } return value; } }
llvm::Value* Load::ResizeIntegerIfNeed(llvm::Value* value, llvm::Type* value_type, ETYPE destination_type, bool sign, llvm::IRBuilder<>& builder) { // Get size differences. int value_type_bw = value_type->getIntegerBitWidth(); size_t type_size = GetTypeSize(type_); if (value_type_bw != type_size) { // Then it depends on sign. value = HandleIntegerTypeCast(value, ConvertType(type_), value_type_bw, type_size, sign, builder); } return value; }