1/*
2 * Copyright (C) 2013 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "FTLOutput.h"
28
29#if ENABLE(FTL_JIT)
30
31namespace JSC { namespace FTL {
32
33Output::Output(LContext context)
34    : IntrinsicRepository(context)
35    , m_function(0)
36    , m_heaps(0)
37    , m_builder(llvm->CreateBuilderInContext(m_context))
38    , m_block(0)
39    , m_nextBlock(0)
40{
41}
42
43Output::~Output()
44{
45    llvm->DisposeBuilder(m_builder);
46}
47
48void Output::initialize(LModule module, LValue function, AbstractHeapRepository& heaps)
49{
50    IntrinsicRepository::initialize(module);
51    m_function = function;
52    m_heaps = &heaps;
53}
54
55LBasicBlock Output::appendTo(LBasicBlock block, LBasicBlock nextBlock)
56{
57    appendTo(block);
58    return insertNewBlocksBefore(nextBlock);
59}
60
61void Output::appendTo(LBasicBlock block)
62{
63    m_block = block;
64
65    llvm->PositionBuilderAtEnd(m_builder, block);
66}
67
68LBasicBlock Output::newBlock(const char* name)
69{
70    if (!m_nextBlock)
71        return appendBasicBlock(m_context, m_function, name);
72    return insertBasicBlock(m_context, m_nextBlock, name);
73}
74
75LValue Output::sensibleDoubleToInt(LValue value)
76{
77    RELEASE_ASSERT(isX86());
78    return call(
79        x86SSE2CvtTSD2SIIntrinsic(),
80        insertElement(
81            insertElement(getUndef(vectorType(doubleType, 2)), value, int32Zero),
82            doubleZero, int32One));
83}
84
85LValue Output::load(TypedPointer pointer, LType refType)
86{
87    LValue result = get(intToPtr(pointer.value(), refType));
88    pointer.heap().decorateInstruction(result, *m_heaps);
89    return result;
90}
91
92void Output::store(LValue value, TypedPointer pointer, LType refType)
93{
94    LValue result = set(value, intToPtr(pointer.value(), refType));
95    pointer.heap().decorateInstruction(result, *m_heaps);
96}
97
98LValue Output::baseIndex(LValue base, LValue index, Scale scale, ptrdiff_t offset)
99{
100    LValue accumulatedOffset;
101
102    switch (scale) {
103    case ScaleOne:
104        accumulatedOffset = index;
105        break;
106    case ScaleTwo:
107        accumulatedOffset = shl(index, intPtrOne);
108        break;
109    case ScaleFour:
110        accumulatedOffset = shl(index, intPtrTwo);
111        break;
112    case ScaleEight:
113    case ScalePtr:
114        accumulatedOffset = shl(index, intPtrThree);
115        break;
116    }
117
118    if (offset)
119        accumulatedOffset = add(accumulatedOffset, constIntPtr(offset));
120
121    return add(base, accumulatedOffset);
122}
123
124void Output::branch(LValue condition, LBasicBlock taken, Weight takenWeight, LBasicBlock notTaken, Weight notTakenWeight)
125{
126    LValue branch = buildCondBr(m_builder, condition, taken, notTaken);
127
128    if (!takenWeight || !notTakenWeight)
129        return;
130
131    double total = takenWeight.value() + notTakenWeight.value();
132
133    setMetadata(
134        branch, profKind,
135        mdNode(
136            m_context, branchWeights,
137            constInt32(takenWeight.scaleToTotal(total)),
138            constInt32(notTakenWeight.scaleToTotal(total))));
139}
140
141void Output::crashNonTerminal()
142{
143    call(intToPtr(constIntPtr(abort), pointerType(functionType(voidType))));
144}
145
146} } // namespace JSC::FTL
147
148#endif // ENABLE(FTL_JIT)
149
150