| /* |
| * Copyright (C) 2013, 2014 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::check(LValue condition, WeightedTarget taken, Weight notTakenWeight) |
| { |
| LBasicBlock continuation = FTL_NEW_BLOCK(*this, ("Output::check continuation")); |
| branch(condition, taken, WeightedTarget(continuation, notTakenWeight)); |
| appendTo(continuation); |
| } |
| |
| void Output::check(LValue condition, WeightedTarget taken) |
| { |
| check(condition, taken, taken.weight().inverse()); |
| } |
| |
| } } // namespace JSC::FTL |
| |
| #endif // ENABLE(FTL_JIT) |
| |