1/*
2 * Copyright (C) 2017-2018 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 "AirDisassembler.h"
28
29#if ENABLE(B3_JIT)
30
31#include "AirBasicBlock.h"
32#include "AirCode.h"
33#include "AirInst.h"
34#include "B3Value.h"
35#include "Disassembler.h"
36#include "LinkBuffer.h"
37
38namespace JSC { namespace B3 { namespace Air {
39
40void Disassembler::startEntrypoint(CCallHelpers& jit)
41{
42 m_entrypointStart = jit.labelIgnoringWatchpoints();
43}
44
45void Disassembler::endEntrypoint(CCallHelpers& jit)
46{
47 m_entrypointEnd = jit.labelIgnoringWatchpoints();
48}
49
50void Disassembler::startLatePath(CCallHelpers& jit)
51{
52 m_latePathStart = jit.labelIgnoringWatchpoints();
53}
54
55void Disassembler::endLatePath(CCallHelpers& jit)
56{
57 m_latePathEnd = jit.labelIgnoringWatchpoints();
58}
59
60void Disassembler::startBlock(BasicBlock* block, CCallHelpers& jit)
61{
62 UNUSED_PARAM(jit);
63 m_blocks.append(block);
64}
65
66void Disassembler::addInst(Inst* inst, CCallHelpers::Label start, CCallHelpers::Label end)
67{
68 auto addResult = m_instToRange.add(inst, std::make_pair(start, end));
69 RELEASE_ASSERT(addResult.isNewEntry);
70}
71
72void Disassembler::dump(Code& code, PrintStream& out, LinkBuffer& linkBuffer, const char* airPrefix, const char* asmPrefix, const ScopedLambda<void(Inst&)>& doToEachInst)
73{
74 auto dumpAsmRange = [&] (CCallHelpers::Label startLabel, CCallHelpers::Label endLabel) {
75 RELEASE_ASSERT(startLabel.isSet());
76 RELEASE_ASSERT(endLabel.isSet());
77 CodeLocationLabel<DisassemblyPtrTag> start = linkBuffer.locationOf<DisassemblyPtrTag>(startLabel);
78 CodeLocationLabel<DisassemblyPtrTag> end = linkBuffer.locationOf<DisassemblyPtrTag>(endLabel);
79 RELEASE_ASSERT(end.dataLocation<uintptr_t>() >= start.dataLocation<uintptr_t>());
80 disassemble(start, end.dataLocation<uintptr_t>() - start.dataLocation<uintptr_t>(), asmPrefix, out);
81 };
82
83 for (BasicBlock* block : m_blocks) {
84 block->dumpHeader(out);
85 if (code.isEntrypoint(block))
86 dumpAsmRange(m_entrypointStart, m_entrypointEnd);
87
88 for (Inst& inst : *block) {
89 doToEachInst(inst);
90
91 out.print(airPrefix);
92 inst.dump(out);
93 out.print("\n");
94
95 auto iter = m_instToRange.find(&inst);
96 if (iter == m_instToRange.end()) {
97 RELEASE_ASSERT(&inst == &block->last());
98 continue;
99 }
100 auto pair = iter->value;
101 dumpAsmRange(pair.first, pair.second);
102 }
103 block->dumpFooter(out);
104 }
105
106 // FIXME: We could be better about various late paths. We can implement
107 // this later if we find a strong use for it.
108 out.print("# Late paths\n");
109 dumpAsmRange(m_latePathStart, m_latePathEnd);
110}
111
112} } } // namespace JSC::B3::Air
113
114#endif // ENABLE(B3_JIT)
115