//===-- valueparser.cpp ---------------------------------------------------===// // // LDC – the LLVM D compiler // // This file is distributed under the Boost Software License. See the LICENSE // file for details. // //===----------------------------------------------------------------------===// #include "valueparser.h" #include #include #include #include "utils.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/Support/raw_ostream.h" namespace { template llvm::ConstantInt *getInt(llvm::LLVMContext &context, const void *data) { assert(nullptr != data); const T val = *static_cast(data); return llvm::ConstantInt::get(context, llvm::APInt(sizeof(T) * 8, val, true)); } template llvm::ConstantFP *getFloat(llvm::LLVMContext &context, const void *data) { assert(nullptr != data); const T val = *static_cast(data); return llvm::ConstantFP::get(context, llvm::APFloat(val)); } llvm::Constant *getPtr(llvm::LLVMContext &context, llvm::Type *targetType, const void *data) { assert(nullptr != targetType); assert(nullptr != data); const auto val = *static_cast(data); return llvm::ConstantExpr::getIntToPtr( llvm::ConstantInt::get(context, llvm::APInt(sizeof(val) * 8, val)), targetType); } } llvm::Constant *parseInitializer(const Context &context, const llvm::DataLayout &dataLayout, llvm::Type *type, const void *data) { assert(nullptr != type); assert(nullptr != data); auto &llcontext = type->getContext(); if (type->isIntegerTy()) { const auto width = type->getIntegerBitWidth(); switch (width) { case 8: return getInt(llcontext, data); case 16: return getInt(llcontext, data); case 32: return getInt(llcontext, data); case 64: return getInt(llcontext, data); default: fatal(context, std::string("Invalid int bit width: ") + std::to_string(width)); } } if (type->isFloatingPointTy()) { const auto width = type->getPrimitiveSizeInBits(); switch (width) { case 32: return getFloat(llcontext, data); case 64: return getFloat(llcontext, data); default: fatal(context, std::string("Invalid fp bit width: ") + std::to_string(width)); } } if (type->isPointerTy()) { return getPtr(llcontext, type, data); } if (type->isStructTy()) { auto stype = llvm::cast(type); auto slayout = dataLayout.getStructLayout(stype); auto numElements = stype->getNumElements(); llvm::SmallVector elements(numElements); for (unsigned i = 0; i < numElements; ++i) { const auto elemType = stype->getElementType(i); const auto elemOffset = slayout->getElementOffset(i); const auto elemPtr = static_cast(data) + elemOffset; elements[i] = parseInitializer(context, dataLayout, elemType, elemPtr); } return llvm::ConstantStruct::get(stype, elements); } if (type->isArrayTy()) { auto elemType = type->getArrayElementType(); const auto step = dataLayout.getTypeAllocSize(elemType); const auto numElements = type->getArrayNumElements(); llvm::SmallVector elements(numElements); for (uint64_t i = 0; i < numElements; ++i) { const auto elemPtr = static_cast(data) + step * i; elements[i] = parseInitializer(context, dataLayout, elemType, elemPtr); } return llvm::ConstantArray::get(llvm::cast(type), elements); } std::string tname; llvm::raw_string_ostream os(tname); type->print(os, true); fatal(context, std::string("Unhandled type: ") + os.str()); return nullptr; }