/* * Copyright (C) 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "FTLOutput.h" #if ENABLE(FTL_JIT) namespace JSC { namespace FTL { Output::Output(LContext context) : IntrinsicRepository(context) , m_function(0) , m_heaps(0) , m_builder(llvm->CreateBuilderInContext(m_context)) , m_block(0) , m_nextBlock(0) { } Output::~Output() { llvm->DisposeBuilder(m_builder); } void Output::initialize(LModule module, LValue function, AbstractHeapRepository& heaps) { IntrinsicRepository::initialize(module); m_function = function; m_heaps = &heaps; } LBasicBlock Output::appendTo(LBasicBlock block, LBasicBlock nextBlock) { appendTo(block); return insertNewBlocksBefore(nextBlock); } void Output::appendTo(LBasicBlock block) { m_block = block; llvm->PositionBuilderAtEnd(m_builder, block); } LBasicBlock Output::newBlock(const char* name) { if (!m_nextBlock) return appendBasicBlock(m_context, m_function, name); return insertBasicBlock(m_context, m_nextBlock, name); } LValue Output::sensibleDoubleToInt(LValue value) { RELEASE_ASSERT(isX86()); return call( x86SSE2CvtTSD2SIIntrinsic(), insertElement( insertElement(getUndef(vectorType(doubleType, 2)), value, int32Zero), doubleZero, int32One)); } LValue Output::load(TypedPointer pointer, LType refType) { LValue result = get(intToPtr(pointer.value(), refType)); pointer.heap().decorateInstruction(result, *m_heaps); return result; } void Output::store(LValue value, TypedPointer pointer, LType refType) { LValue result = set(value, intToPtr(pointer.value(), refType)); pointer.heap().decorateInstruction(result, *m_heaps); } LValue Output::baseIndex(LValue base, LValue index, Scale scale, ptrdiff_t offset) { LValue accumulatedOffset; switch (scale) { case ScaleOne: accumulatedOffset = index; break; case ScaleTwo: accumulatedOffset = shl(index, intPtrOne); break; case ScaleFour: accumulatedOffset = shl(index, intPtrTwo); break; case ScaleEight: case ScalePtr: accumulatedOffset = shl(index, intPtrThree); break; } if (offset) accumulatedOffset = add(accumulatedOffset, constIntPtr(offset)); return add(base, accumulatedOffset); } void Output::branch(LValue condition, LBasicBlock taken, Weight takenWeight, LBasicBlock notTaken, Weight notTakenWeight) { LValue branch = buildCondBr(m_builder, condition, taken, notTaken); if (!takenWeight || !notTakenWeight) return; double total = takenWeight.value() + notTakenWeight.value(); setMetadata( branch, profKind, mdNode( m_context, branchWeights, constInt32(takenWeight.scaleToTotal(total)), constInt32(notTakenWeight.scaleToTotal(total)))); } void Output::crashNonTerminal() { call(intToPtr(constIntPtr(abort), pointerType(functionType(voidType)))); } } } // namespace JSC::FTL #endif // ENABLE(FTL_JIT)