llvm::Value* getSingleTranslatedArgument(Function& functionGenerator, llvm::Value* const argValue, const SEM::Type* const parameterType, const SEM::Type* const translatedParameterType) { auto& builder = functionGenerator.getBuilder(); auto& module = functionGenerator.module(); const auto llvmParameterType = genArgType(module, parameterType); const auto llvmTranslatedParameterType = genArgType(module, translatedParameterType); // Being able to pass the inner parameter type by value must imply // that the outer parameter type can be passed by value. assert(checkImplies(canPassByValue(module, parameterType), canPassByValue(module, translatedParameterType))); if (!canPassByValue(module, parameterType) && canPassByValue(module, translatedParameterType)) { // Create an alloca to hinner the parameter so it can be passed by pointer // into the target function. const auto argAlloca = genAlloca(functionGenerator, translatedParameterType); genStore(functionGenerator, argValue, argAlloca, translatedParameterType); return builder.CreatePointerCast(argAlloca, llvmParameterType); } else if (llvmParameterType->isPointerTy() && llvmTranslatedParameterType->isPointerTy()) { // Make sure our pointers have the right type. return builder.CreatePointerCast(argValue, llvmParameterType); } else { return argValue; } }
bool FunctionState::hasValue(llvm::Instruction const *ForInstruction) const { if (!isDominatedByActive(ForInstruction)) return false; auto const Type = ForInstruction->getType(); if (Type->isIntegerTy()) { return ValuesUInt64.count(ForInstruction); } else if (Type->isPointerTy()) { return ValuesPtr.count(ForInstruction); } else if (Type->isFloatTy()) { return ValuesFloat.count(ForInstruction); } else if (Type->isDoubleTy()) { return ValuesDouble.count(ForInstruction); } else if (Type->isX86_FP80Ty() || Type->isFP128Ty() || Type->isPPC_FP128Ty()) { return ValuesAPFloat.count(ForInstruction); } else { return false; } }
llvm::Type *emit_alloc_type(T const& t) { auto const ty = emit(t); if (ty->isPointerTy()) { return ty->getPointerElementType(); } else { return ty; } }
void FunctionState::clearValue(llvm::Instruction const *ForInstruction) { auto const Type = ForInstruction->getType(); if (Type->isIntegerTy()) { ValuesUInt64.erase(ForInstruction); } else if (Type->isPointerTy()) { ValuesPtr.erase(ForInstruction); } else if (Type->isFloatTy()) { ValuesFloat.erase(ForInstruction); } else if (Type->isDoubleTy()) { ValuesDouble.erase(ForInstruction); } else if (Type->isX86_FP80Ty() || Type->isFP128Ty() || Type->isPPC_FP128Ty()) { ValuesAPFloat.erase(ForInstruction); } }
/// Print a textual description of a FunctionState. llvm::raw_ostream &operator<<(llvm::raw_ostream &Out, FunctionState const &State) { Out << " Function [Index=" << State.getIndex() << "]\n"; Out << " Allocas:\n"; for (auto const &Alloca : State.getAllocas()) { Out << " " << Alloca.getInstructionIndex() << " =[" << Alloca.getElementCount() << "x" << Alloca.getElementSize() << "] @" << Alloca.getAddress() << "\n"; } Out << " Instruction values [Active="; if (State.getActiveInstructionIndex().assigned(0)) Out << State.getActiveInstructionIndex().get<0>(); else Out << "unassigned"; Out << "]:\n"; auto const InstructionCount = State.getInstructionCount(); for (std::size_t i = 0; i < InstructionCount; ++i) { auto const Instruction = State.getInstruction(i); auto const Type = Instruction->getType(); if (llvm::isa<llvm::IntegerType>(Type)) { auto const Value = State.getValueUInt64(Instruction); if (Value.assigned<uint64_t>()) { Out << " " << i << " = (uint64_t)" << Value.get<uint64_t>() << "\n"; } } else if (Type->isPointerTy()) { auto const Value = State.getValuePtr(Instruction); if (Value.assigned<stateptr_ty>()) { Out << " " << i << " = (? *)" << Value.get<stateptr_ty>() << "\n"; } } else if (Type->isFloatTy()) { auto const Value = State.getValueFloat(Instruction); if (Value.assigned<float>()) { Out << " " << i << " = (float)" << Value.get<float>() << "\n"; } } else if (Type->isDoubleTy()) { auto const Value = State.getValueDouble(Instruction); if (Value.assigned<double>()) { Out << " " << i << " = (double)" << Value.get<double>() << "\n"; } } else if (Type->isX86_FP80Ty() || Type->isFP128Ty() || Type->isPPC_FP128Ty()) { auto const Value = State.getValueAPFloat(Instruction); if (Value.assigned<llvm::APFloat>()) { llvm::SmallString<32> Buffer; Value.get<llvm::APFloat>().toString(Buffer); Out << " " << i << " = (long double)" << Buffer << "\n"; } } } return Out; }
void printComparable(llvm::raw_ostream &Out, FunctionState const &State) { Out << " Function [Index=" << State.getIndex() << "]\n"; Out << " Allocas:\n"; for (auto const &Alloca : State.getAllocas()) { Out << " " << Alloca.getInstructionIndex() << " =[" << Alloca.getElementCount() << "x" << Alloca.getElementSize() << "]\n"; } Out << " Instruction values [Active="; if (State.getActiveInstructionIndex().assigned(0)) Out << State.getActiveInstructionIndex().get<0>(); else Out << "unassigned"; Out << "]:\n"; auto const InstructionCount = State.getInstructionCount(); for (std::size_t i = 0; i < InstructionCount; ++i) { auto const Instruction = State.getInstruction(i); auto const Type = Instruction->getType(); if (llvm::isa<llvm::IntegerType>(Type)) { auto const UValue = State.getValueUInt64(Instruction); if (UValue.assigned<uint64_t>()) { auto const SValue = State.getValueInt64(Instruction); assert(SValue.assigned<int64_t>()); Out << " " << i << " = (int64_t)" << SValue.get< int64_t>() << ", (uint64_t)" << UValue.get<uint64_t>() << "\n"; } } else if (Type->isPointerTy()) { auto const Value = State.getValuePtr(Instruction); if (Value.assigned<stateptr_ty>()) { Out << " " << i << " = \n"; // TODO: a comparable pointer representation (this requires us to // determine the allocation that a pointer references, and then // display the pointer value relative to that allocation). } } else if (Type->isFloatTy()) { auto const Value = State.getValueFloat(Instruction); if (Value.assigned<float>()) { Out << " " << i << " = (float)" << Value.get<float>() << "\n"; } } else if (Type->isDoubleTy()) { auto const Value = State.getValueDouble(Instruction); if (Value.assigned<double>()) { Out << " " << i << " = (double)" << Value.get<double>() << "\n"; } } else if (Type->isX86_FP80Ty() || Type->isFP128Ty() || Type->isPPC_FP128Ty()) { auto const Value = State.getValueAPFloat(Instruction); if (Value.assigned<llvm::APFloat>()) { llvm::SmallString<32> Buffer; Value.get<llvm::APFloat>().toString(Buffer); Out << " " << i << " = (long double)" << Buffer << "\n"; } } } }