Error CodeBuilder::embedConstPool(const Label& label, const ConstPool& pool) { if (_lastError) return _lastError; if (!isLabelValid(label)) return setLastError(DebugUtils::errored(kErrorInvalidLabel)); ASMJIT_PROPAGATE(align(kAlignData, static_cast<uint32_t>(pool.getAlignment()))); ASMJIT_PROPAGATE(bind(label)); CBData* node = newDataNode(nullptr, static_cast<uint32_t>(pool.getSize())); if (ASMJIT_UNLIKELY(!node)) return setLastError(DebugUtils::errored(kErrorNoHeapMemory)); pool.fill(node->getData()); addNode(node); return kErrorOk; }
Error CodeBuilder::registerLabelNode(CBLabel* node) noexcept { if (_lastError) return _lastError; ASMJIT_ASSERT(_code != nullptr); // Don't call setLastError() from here, we are noexcept and we are called // by `newLabelNode()` and `newFuncNode()`, which are noexcept as well. uint32_t id; ASMJIT_PROPAGATE(_code->newLabelId(id)); size_t index = Operand::unpackId(id); // We just added one label so it must be true. ASMJIT_ASSERT(_cbLabels.getLength() < index + 1); ASMJIT_PROPAGATE(_cbLabels.resize(index + 1)); _cbLabels[index] = node; node->_id = id; return kErrorOk; }
ASMJIT_FAVOR_SIZE Error CodeBuilder::addPass(CBPass* pass) noexcept { if (ASMJIT_UNLIKELY(pass == nullptr)) { // Since this is directly called by `addPassT()` we treat `null` argument // as out-of-memory condition. Otherwise it would be API misuse. return DebugUtils::errored(kErrorNoHeapMemory); } else if (ASMJIT_UNLIKELY(pass->_cb)) { // Kind of weird, but okay... if (pass->_cb == this) return kErrorOk; return DebugUtils::errored(kErrorInvalidState); } ASMJIT_PROPAGATE(_cbPasses.append(pass)); pass->_cb = this; return kErrorOk; }
ASMJIT_FAVOR_SIZE Error FuncDetail::init(const FuncSignature& sign) { uint32_t ccId = sign.getCallConv(); CallConv& cc = _callConv; uint32_t argCount = sign.getArgCount(); if (ASMJIT_UNLIKELY(argCount > kFuncArgCount)) return DebugUtils::errored(kErrorInvalidArgument); ASMJIT_PROPAGATE(cc.init(ccId)); uint32_t gpSize = (cc.getArchType() == ArchInfo::kTypeX86) ? 4 : 8; uint32_t deabstractDelta = TypeId::deabstractDeltaOfSize(gpSize); const uint8_t* args = sign.getArgs(); for (uint32_t i = 0; i < argCount; i++) { Value& arg = _args[i]; arg.initTypeId(TypeId::deabstract(args[i], deabstractDelta)); } _argCount = static_cast<uint8_t>(argCount); uint32_t ret = sign.getRet(); if (ret != TypeId::kVoid) { _rets[0].initTypeId(TypeId::deabstract(ret, deabstractDelta)); _retCount = 1; } #if defined(ASMJIT_BUILD_X86) if (CallConv::isX86Family(ccId)) return X86Internal::initFuncDetail(*this, sign, gpSize); #endif // ASMJIT_BUILD_X86 #if defined(ASMJIT_BUILD_ARM) if (CallConv::isArmFamily(ccId)) return ArmInternal::initFuncDetail(*this, sign, gpSize); #endif // ASMJIT_BUILD_ARM // We should never bubble here as if `cc.init()` succeeded then there has to // be an implementation for the current architecture. However, stay safe. return DebugUtils::errored(kErrorInvalidArgument); }
Error CodeBuilder::getCBLabel(CBLabel** pOut, uint32_t id) noexcept { if (_lastError) return _lastError; ASMJIT_ASSERT(_code != nullptr); size_t index = Operand::unpackId(id); if (ASMJIT_UNLIKELY(index >= _code->getLabelsCount())) return DebugUtils::errored(kErrorInvalidLabel); if (index >= _cbLabels.getLength()) ASMJIT_PROPAGATE(_cbLabels.resize(index + 1)); CBLabel* node = _cbLabels[index]; if (!node) { node = newNodeT<CBLabel>(id); if (ASMJIT_UNLIKELY(!node)) return DebugUtils::errored(kErrorNoHeapMemory); _cbLabels[index] = node; } *pOut = node; return kErrorOk; }