Doxygenize the documentation comments
There were many // comment used to document classes, functions etc. but
those are not picked up by doxygen which expects /// comments. This
converts many comments from // to /// in order to improve the generated
documentation.
BUG=
R=jvoung@chromium.org, kschimpf@google.com
Review URL: https://codereview.chromium.org/1216963007.
diff --git a/src/IceAPInt.h b/src/IceAPInt.h
index 01ce280..9ef0702 100644
--- a/src/IceAPInt.h
+++ b/src/IceAPInt.h
@@ -47,8 +47,8 @@
uint64_t getRawData() const { return Val; }
private:
- uint32_t BitWidth; // The number of bits in this APInt.
- uint64_t Val; // The (64-bit) equivalent integer value.
+ uint32_t BitWidth; /// The number of bits in this APInt.
+ uint64_t Val; /// The (64-bit) equivalent integer value.
/// Clear unused high order bits.
void clearUnusedBits() {
diff --git a/src/IceAssembler.cpp b/src/IceAssembler.cpp
index 94cb5a1..48db036 100644
--- a/src/IceAssembler.cpp
+++ b/src/IceAssembler.cpp
@@ -17,9 +17,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the Assembler base class.
-//
+///
+/// \file
+/// This file implements the Assembler base class.
+///
//===----------------------------------------------------------------------===//
#include "IceAssembler.h"
diff --git a/src/IceAssembler.h b/src/IceAssembler.h
index c2a40d6..437dfc3 100644
--- a/src/IceAssembler.h
+++ b/src/IceAssembler.h
@@ -13,11 +13,12 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the Assembler base class. Instructions are assembled
-// by architecture-specific assemblers that derive from this base class.
-// This base class manages buffers and fixups for emitting code, etc.
-//
+///
+/// \file
+/// This file declares the Assembler base class. Instructions are assembled
+/// by architecture-specific assemblers that derive from this base class.
+/// This base class manages buffers and fixups for emitting code, etc.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEASSEMBLER_H
@@ -28,7 +29,7 @@
namespace Ice {
-// Assembler buffers are used to emit binary code. They grow on demand.
+/// Assembler buffers are used to emit binary code. They grow on demand.
class AssemblerBuffer {
AssemblerBuffer(const AssemblerBuffer &) = delete;
AssemblerBuffer &operator=(const AssemblerBuffer &) = delete;
@@ -37,7 +38,7 @@
AssemblerBuffer(Assembler &);
~AssemblerBuffer();
- // Basic support for emitting, loading, and storing.
+ /// Basic support for emitting, loading, and storing.
template <typename T> void emit(T Value) {
assert(hasEnsuredCapacity());
*reinterpret_cast<T *>(Cursor) = Value;
@@ -56,21 +57,20 @@
*reinterpret_cast<T *>(Contents + Position) = Value;
}
- // Emit a fixup at the current location.
+ /// Emit a fixup at the current location.
void emitFixup(AssemblerFixup *Fixup) { Fixup->set_position(size()); }
- // Get the size of the emitted code.
+ /// Get the size of the emitted code.
intptr_t size() const { return Cursor - Contents; }
uintptr_t contents() const { return Contents; }
- // To emit an instruction to the assembler buffer, the EnsureCapacity helper
- // must be used to guarantee that the underlying data area is big enough to
- // hold the emitted instruction. Usage:
- //
- // AssemblerBuffer buffer;
- // AssemblerBuffer::EnsureCapacity ensured(&buffer);
- // ... emit bytes for single instruction ...
-
+ /// To emit an instruction to the assembler buffer, the EnsureCapacity helper
+ /// must be used to guarantee that the underlying data area is big enough to
+ /// hold the emitted instruction. Usage:
+ ///
+ /// AssemblerBuffer buffer;
+ /// AssemblerBuffer::EnsureCapacity ensured(&buffer);
+ /// ... emit bytes for single instruction ...
class EnsureCapacity {
EnsureCapacity(const EnsureCapacity &) = delete;
EnsureCapacity &operator=(const EnsureCapacity &) = delete;
@@ -100,10 +100,10 @@
return true;
}
- // Returns the position in the instruction stream.
+ /// Returns the position in the instruction stream.
intptr_t getPosition() const { return Cursor - Contents; }
- // Create and track a fixup in the current function.
+ /// Create and track a fixup in the current function.
AssemblerFixup *createFixup(FixupKind Kind, const Constant *Value);
const FixupRefList &fixups() const { return Fixups; }
@@ -114,9 +114,9 @@
}
private:
- // The limit is set to kMinimumGap bytes before the end of the data area.
- // This leaves enough space for the longest possible instruction and allows
- // for a single, fast space check per instruction.
+ /// The limit is set to kMinimumGap bytes before the end of the data area.
+ /// This leaves enough space for the longest possible instruction and allows
+ /// for a single, fast space check per instruction.
static constexpr intptr_t kMinimumGap = 32;
uintptr_t Contents;
@@ -124,7 +124,7 @@
uintptr_t Limit;
// The member variable is named Assemblr to avoid hiding the class Assembler.
Assembler &Assemblr;
- // List of pool-allocated fixups relative to the current function.
+ /// List of pool-allocated fixups relative to the current function.
FixupRefList Fixups;
uintptr_t cursor() const { return Cursor; }
@@ -134,8 +134,8 @@
return (Limit - Contents) + kMinimumGap;
}
- // Compute the limit based on the data area and the capacity. See
- // description of kMinimumGap for the reasoning behind the value.
+ /// Compute the limit based on the data area and the capacity. See
+ /// description of kMinimumGap for the reasoning behind the value.
static uintptr_t computeLimit(uintptr_t Data, intptr_t Capacity) {
return Data + Capacity - kMinimumGap;
}
@@ -158,7 +158,7 @@
virtual ~Assembler() = default;
- // Allocate a chunk of bytes using the per-Assembler allocator.
+ /// Allocate a chunk of bytes using the per-Assembler allocator.
uintptr_t allocateBytes(size_t bytes) {
// For now, alignment is not related to NaCl bundle alignment, since
// the buffer's GetPosition is relative to the base. So NaCl bundle
@@ -170,13 +170,13 @@
return reinterpret_cast<uintptr_t>(Allocator.Allocate(bytes, Alignment));
}
- // Allocate data of type T using the per-Assembler allocator.
+ /// Allocate data of type T using the per-Assembler allocator.
template <typename T> T *allocate() { return Allocator.Allocate<T>(); }
- // Align the tail end of the function to the required target alignment.
+ /// Align the tail end of the function to the required target alignment.
virtual void alignFunction() = 0;
- // Add nop padding of a particular width to the current bundle.
+ /// Add nop padding of a particular width to the current bundle.
virtual void padWithNop(intptr_t Padding) = 0;
virtual SizeT getBundleAlignLog2Bytes() const = 0;
@@ -184,8 +184,8 @@
virtual const char *getNonExecPadDirective() const = 0;
virtual llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const = 0;
- // Mark the current text location as the start of a CFG node
- // (represented by NodeNumber).
+ /// Mark the current text location as the start of a CFG node
+ /// (represented by NodeNumber).
virtual void bindCfgNodeLabel(SizeT NodeNumber) = 0;
virtual bool fixupIsPCRel(FixupKind Kind) const = 0;
@@ -205,7 +205,7 @@
const IceString &getFunctionName() { return FunctionName; }
void setFunctionName(const IceString &NewName) { FunctionName = NewName; }
intptr_t getBufferSize() const { return Buffer.size(); }
- // Roll back to a (smaller) size.
+ /// Roll back to a (smaller) size.
void setBufferSize(intptr_t NewSize) { Buffer.setSize(NewSize); }
void setPreliminary(bool Value) { Preliminary = Value; }
bool getPreliminary() const { return Preliminary; }
@@ -220,15 +220,15 @@
const AssemblerKind Kind;
ArenaAllocator<32 * 1024> Allocator;
- // FunctionName and IsInternal are transferred from the original Cfg
- // object, since the Cfg object may be deleted by the time the
- // assembler buffer is emitted.
+ /// FunctionName and IsInternal are transferred from the original Cfg
+ /// object, since the Cfg object may be deleted by the time the
+ /// assembler buffer is emitted.
IceString FunctionName = "";
bool IsInternal = false;
- // Preliminary indicates whether a preliminary pass is being made
- // for calculating bundle padding (Preliminary=true), versus the
- // final pass where all changes to label bindings, label links, and
- // relocation fixups are fully committed (Preliminary=false).
+ /// Preliminary indicates whether a preliminary pass is being made
+ /// for calculating bundle padding (Preliminary=true), versus the
+ /// final pass where all changes to label bindings, label links, and
+ /// relocation fixups are fully committed (Preliminary=false).
bool Preliminary = false;
protected:
diff --git a/src/IceAssemblerARM32.h b/src/IceAssemblerARM32.h
index f67b630..977b43d 100644
--- a/src/IceAssemblerARM32.h
+++ b/src/IceAssemblerARM32.h
@@ -14,9 +14,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the Assembler class for ARM32.
-//
+///
+/// \file
+/// This file implements the Assembler class for ARM32.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEASSEMBLERARM32_H
diff --git a/src/IceAssemblerMIPS32.h b/src/IceAssemblerMIPS32.h
index fc83919..b088d56 100644
--- a/src/IceAssemblerMIPS32.h
+++ b/src/IceAssemblerMIPS32.h
@@ -14,9 +14,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the Assembler class for MIPS32.
-//
+///
+/// \file
+/// This file implements the Assembler class for MIPS32.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEASSEMBLERMIPS32_H
diff --git a/src/IceAssemblerX8632.cpp b/src/IceAssemblerX8632.cpp
new file mode 100644
index 0000000..6135b5c
--- /dev/null
+++ b/src/IceAssemblerX8632.cpp
@@ -0,0 +1,2559 @@
+//===- subzero/src/IceAssemblerX8632.cpp - Assembler for x86-32 ----------===//
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Modified by the Subzero authors.
+//
+//===----------------------------------------------------------------------===//
+//
+// The Subzero Code Generator
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file implements the Assembler class for x86-32.
+///
+//===----------------------------------------------------------------------===//
+
+#include "IceAssemblerX8632.h"
+
+#include "IceCfg.h"
+#include "IceOperand.h"
+
+namespace Ice {
+namespace X8632 {
+
+Address Address::ofConstPool(Assembler *Asm, const Constant *Imm) {
+ AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Imm);
+ const RelocOffsetT Offset = 0;
+ return Address::Absolute(Offset, Fixup);
+}
+
+AssemblerX8632::~AssemblerX8632() {
+ if (BuildDefs::asserts()) {
+ for (const Label *Label : CfgNodeLabels) {
+ Label->FinalCheck();
+ }
+ for (const Label *Label : LocalLabels) {
+ Label->FinalCheck();
+ }
+ }
+}
+
+void AssemblerX8632::alignFunction() {
+ SizeT Align = 1 << getBundleAlignLog2Bytes();
+ SizeT BytesNeeded = Utils::OffsetToAlignment(Buffer.getPosition(), Align);
+ const SizeT HltSize = 1;
+ while (BytesNeeded > 0) {
+ hlt();
+ BytesNeeded -= HltSize;
+ }
+}
+
+Label *AssemblerX8632::GetOrCreateLabel(SizeT Number, LabelVector &Labels) {
+ Label *L = nullptr;
+ if (Number == Labels.size()) {
+ L = new (this->allocate<Label>()) Label();
+ Labels.push_back(L);
+ return L;
+ }
+ if (Number > Labels.size()) {
+ Labels.resize(Number + 1);
+ }
+ L = Labels[Number];
+ if (!L) {
+ L = new (this->allocate<Label>()) Label();
+ Labels[Number] = L;
+ }
+ return L;
+}
+
+Label *AssemblerX8632::GetOrCreateCfgNodeLabel(SizeT NodeNumber) {
+ return GetOrCreateLabel(NodeNumber, CfgNodeLabels);
+}
+
+Label *AssemblerX8632::GetOrCreateLocalLabel(SizeT Number) {
+ return GetOrCreateLabel(Number, LocalLabels);
+}
+
+void AssemblerX8632::bindCfgNodeLabel(SizeT NodeNumber) {
+ assert(!getPreliminary());
+ Label *L = GetOrCreateCfgNodeLabel(NodeNumber);
+ this->bind(L);
+}
+
+void AssemblerX8632::BindLocalLabel(SizeT Number) {
+ Label *L = GetOrCreateLocalLabel(Number);
+ if (!getPreliminary())
+ this->bind(L);
+}
+
+void AssemblerX8632::call(GPRRegister reg) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xFF);
+ emitRegisterOperand(2, reg);
+}
+
+void AssemblerX8632::call(const Address &address) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xFF);
+ emitOperand(2, address);
+}
+
+void AssemblerX8632::call(const ConstantRelocatable *label) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ intptr_t call_start = Buffer.getPosition();
+ emitUint8(0xE8);
+ emitFixup(this->createFixup(llvm::ELF::R_386_PC32, label));
+ emitInt32(-4);
+ assert((Buffer.getPosition() - call_start) == kCallExternalLabelSize);
+ (void)call_start;
+}
+
+void AssemblerX8632::call(const Immediate &abs_address) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ intptr_t call_start = Buffer.getPosition();
+ emitUint8(0xE8);
+ emitFixup(
+ this->createFixup(llvm::ELF::R_386_PC32, AssemblerFixup::NullSymbol));
+ emitInt32(abs_address.value() - 4);
+ assert((Buffer.getPosition() - call_start) == kCallExternalLabelSize);
+ (void)call_start;
+}
+
+void AssemblerX8632::pushl(GPRRegister reg) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x50 + reg);
+}
+
+void AssemblerX8632::popl(GPRRegister reg) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x58 + reg);
+}
+
+void AssemblerX8632::popl(const Address &address) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x8F);
+ emitOperand(0, address);
+}
+
+void AssemblerX8632::pushal() {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x60);
+}
+
+void AssemblerX8632::popal() {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x61);
+}
+
+void AssemblerX8632::setcc(CondX86::BrCond condition, ByteRegister dst) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x90 + condition);
+ emitUint8(0xC0 + dst);
+}
+
+void AssemblerX8632::setcc(CondX86::BrCond condition, const Address &address) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x90 + condition);
+ emitOperand(0, address);
+}
+
+void AssemblerX8632::mov(Type Ty, GPRRegister dst, const Immediate &imm) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (isByteSizedType(Ty)) {
+ emitUint8(0xB0 + dst);
+ emitUint8(imm.value() & 0xFF);
+ return;
+ }
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ emitUint8(0xB8 + dst);
+ emitImmediate(Ty, imm);
+}
+
+void AssemblerX8632::mov(Type Ty, GPRRegister dst, GPRRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (isByteSizedType(Ty)) {
+ emitUint8(0x88);
+ } else {
+ emitUint8(0x89);
+ }
+ emitRegisterOperand(src, dst);
+}
+
+void AssemblerX8632::mov(Type Ty, GPRRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (isByteSizedType(Ty)) {
+ emitUint8(0x8A);
+ } else {
+ emitUint8(0x8B);
+ }
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::mov(Type Ty, const Address &dst, GPRRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (isByteSizedType(Ty)) {
+ emitUint8(0x88);
+ } else {
+ emitUint8(0x89);
+ }
+ emitOperand(src, dst);
+}
+
+void AssemblerX8632::mov(Type Ty, const Address &dst, const Immediate &imm) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (isByteSizedType(Ty)) {
+ emitUint8(0xC6);
+ emitOperand(0, dst);
+ emitUint8(imm.value() & 0xFF);
+ } else {
+ emitUint8(0xC7);
+ emitOperand(0, dst);
+ emitImmediate(Ty, imm);
+ }
+}
+
+void AssemblerX8632::movzx(Type SrcTy, GPRRegister dst, GPRRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ bool ByteSized = isByteSizedType(SrcTy);
+ assert(ByteSized || SrcTy == IceType_i16);
+ emitUint8(0x0F);
+ emitUint8(ByteSized ? 0xB6 : 0xB7);
+ emitRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::movzx(Type SrcTy, GPRRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ bool ByteSized = isByteSizedType(SrcTy);
+ assert(ByteSized || SrcTy == IceType_i16);
+ emitUint8(0x0F);
+ emitUint8(ByteSized ? 0xB6 : 0xB7);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::movsx(Type SrcTy, GPRRegister dst, GPRRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ bool ByteSized = isByteSizedType(SrcTy);
+ assert(ByteSized || SrcTy == IceType_i16);
+ emitUint8(0x0F);
+ emitUint8(ByteSized ? 0xBE : 0xBF);
+ emitRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::movsx(Type SrcTy, GPRRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ bool ByteSized = isByteSizedType(SrcTy);
+ assert(ByteSized || SrcTy == IceType_i16);
+ emitUint8(0x0F);
+ emitUint8(ByteSized ? 0xBE : 0xBF);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::lea(Type Ty, GPRRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(Ty == IceType_i16 || Ty == IceType_i32);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ emitUint8(0x8D);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::cmov(Type Ty, CondX86::BrCond cond, GPRRegister dst,
+ GPRRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ else
+ assert(Ty == IceType_i32);
+ emitUint8(0x0F);
+ emitUint8(0x40 + cond);
+ emitRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::cmov(Type Ty, CondX86::BrCond cond, GPRRegister dst,
+ const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ else
+ assert(Ty == IceType_i32);
+ emitUint8(0x0F);
+ emitUint8(0x40 + cond);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::rep_movsb() {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xF3);
+ emitUint8(0xA4);
+}
+
+void AssemblerX8632::movss(Type Ty, XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
+ emitUint8(0x0F);
+ emitUint8(0x10);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::movss(Type Ty, const Address &dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
+ emitUint8(0x0F);
+ emitUint8(0x11);
+ emitOperand(src, dst);
+}
+
+void AssemblerX8632::movss(Type Ty, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
+ emitUint8(0x0F);
+ emitUint8(0x11);
+ emitXmmRegisterOperand(src, dst);
+}
+
+void AssemblerX8632::movd(XmmRegister dst, GPRRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x6E);
+ emitRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::movd(XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x6E);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::movd(GPRRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x7E);
+ emitRegisterOperand(src, dst);
+}
+
+void AssemblerX8632::movd(const Address &dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x7E);
+ emitOperand(src, dst);
+}
+
+void AssemblerX8632::movq(XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xF3);
+ emitUint8(0x0F);
+ emitUint8(0x7E);
+ emitRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::movq(const Address &dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0xD6);
+ emitOperand(src, dst);
+}
+
+void AssemblerX8632::movq(XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xF3);
+ emitUint8(0x0F);
+ emitUint8(0x7E);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::addss(Type Ty, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
+ emitUint8(0x0F);
+ emitUint8(0x58);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::addss(Type Ty, XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
+ emitUint8(0x0F);
+ emitUint8(0x58);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::subss(Type Ty, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
+ emitUint8(0x0F);
+ emitUint8(0x5C);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::subss(Type Ty, XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
+ emitUint8(0x0F);
+ emitUint8(0x5C);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::mulss(Type Ty, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
+ emitUint8(0x0F);
+ emitUint8(0x59);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::mulss(Type Ty, XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
+ emitUint8(0x0F);
+ emitUint8(0x59);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::divss(Type Ty, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
+ emitUint8(0x0F);
+ emitUint8(0x5E);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::divss(Type Ty, XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
+ emitUint8(0x0F);
+ emitUint8(0x5E);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::fld(Type Ty, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(isFloat32Asserting32Or64(Ty) ? 0xD9 : 0xDD);
+ emitOperand(0, src);
+}
+
+void AssemblerX8632::fstp(Type Ty, const Address &dst) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(isFloat32Asserting32Or64(Ty) ? 0xD9 : 0xDD);
+ emitOperand(3, dst);
+}
+
+void AssemblerX8632::fstp(X87STRegister st) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xDD);
+ emitUint8(0xD8 + st);
+}
+
+void AssemblerX8632::movaps(XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x28);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::movups(XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x10);
+ emitRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::movups(XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x10);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::movups(const Address &dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x11);
+ emitOperand(src, dst);
+}
+
+void AssemblerX8632::padd(Type Ty, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ if (isByteSizedArithType(Ty)) {
+ emitUint8(0xFC);
+ } else if (Ty == IceType_i16) {
+ emitUint8(0xFD);
+ } else {
+ emitUint8(0xFE);
+ }
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::padd(Type Ty, XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ if (isByteSizedArithType(Ty)) {
+ emitUint8(0xFC);
+ } else if (Ty == IceType_i16) {
+ emitUint8(0xFD);
+ } else {
+ emitUint8(0xFE);
+ }
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::pand(Type /* Ty */, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0xDB);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::pand(Type /* Ty */, XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0xDB);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::pandn(Type /* Ty */, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0xDF);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::pandn(Type /* Ty */, XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0xDF);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::pmull(Type Ty, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ if (Ty == IceType_i16) {
+ emitUint8(0xD5);
+ } else {
+ assert(Ty == IceType_i32);
+ emitUint8(0x38);
+ emitUint8(0x40);
+ }
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::pmull(Type Ty, XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ if (Ty == IceType_i16) {
+ emitUint8(0xD5);
+ } else {
+ assert(Ty == IceType_i32);
+ emitUint8(0x38);
+ emitUint8(0x40);
+ }
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::pmuludq(Type /* Ty */, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0xF4);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::pmuludq(Type /* Ty */, XmmRegister dst,
+ const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0xF4);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::por(Type /* Ty */, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0xEB);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::por(Type /* Ty */, XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0xEB);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::psub(Type Ty, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ if (isByteSizedArithType(Ty)) {
+ emitUint8(0xF8);
+ } else if (Ty == IceType_i16) {
+ emitUint8(0xF9);
+ } else {
+ emitUint8(0xFA);
+ }
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::psub(Type Ty, XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ if (isByteSizedArithType(Ty)) {
+ emitUint8(0xF8);
+ } else if (Ty == IceType_i16) {
+ emitUint8(0xF9);
+ } else {
+ emitUint8(0xFA);
+ }
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::pxor(Type /* Ty */, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0xEF);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::pxor(Type /* Ty */, XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0xEF);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::psll(Type Ty, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ if (Ty == IceType_i16) {
+ emitUint8(0xF1);
+ } else {
+ assert(Ty == IceType_i32);
+ emitUint8(0xF2);
+ }
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::psll(Type Ty, XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ if (Ty == IceType_i16) {
+ emitUint8(0xF1);
+ } else {
+ assert(Ty == IceType_i32);
+ emitUint8(0xF2);
+ }
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::psll(Type Ty, XmmRegister dst, const Immediate &imm) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(imm.is_int8());
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ if (Ty == IceType_i16) {
+ emitUint8(0x71);
+ } else {
+ assert(Ty == IceType_i32);
+ emitUint8(0x72);
+ }
+ emitRegisterOperand(6, dst);
+ emitUint8(imm.value() & 0xFF);
+}
+
+void AssemblerX8632::psra(Type Ty, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ if (Ty == IceType_i16) {
+ emitUint8(0xE1);
+ } else {
+ assert(Ty == IceType_i32);
+ emitUint8(0xE2);
+ }
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::psra(Type Ty, XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ if (Ty == IceType_i16) {
+ emitUint8(0xE1);
+ } else {
+ assert(Ty == IceType_i32);
+ emitUint8(0xE2);
+ }
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::psra(Type Ty, XmmRegister dst, const Immediate &imm) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(imm.is_int8());
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ if (Ty == IceType_i16) {
+ emitUint8(0x71);
+ } else {
+ assert(Ty == IceType_i32);
+ emitUint8(0x72);
+ }
+ emitRegisterOperand(4, dst);
+ emitUint8(imm.value() & 0xFF);
+}
+
+void AssemblerX8632::psrl(Type Ty, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ if (Ty == IceType_i16) {
+ emitUint8(0xD1);
+ } else if (Ty == IceType_f64) {
+ emitUint8(0xD3);
+ } else {
+ assert(Ty == IceType_i32 || Ty == IceType_f32 || Ty == IceType_v4f32);
+ emitUint8(0xD2);
+ }
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::psrl(Type Ty, XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ if (Ty == IceType_i16) {
+ emitUint8(0xD1);
+ } else if (Ty == IceType_f64) {
+ emitUint8(0xD3);
+ } else {
+ assert(Ty == IceType_i32 || Ty == IceType_f32 || Ty == IceType_v4f32);
+ emitUint8(0xD2);
+ }
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::psrl(Type Ty, XmmRegister dst, const Immediate &imm) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(imm.is_int8());
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ if (Ty == IceType_i16) {
+ emitUint8(0x71);
+ } else if (Ty == IceType_f64) {
+ emitUint8(0x73);
+ } else {
+ assert(Ty == IceType_i32 || Ty == IceType_f32 || Ty == IceType_v4f32);
+ emitUint8(0x72);
+ }
+ emitRegisterOperand(2, dst);
+ emitUint8(imm.value() & 0xFF);
+}
+
+// {add,sub,mul,div}ps are given a Ty parameter for consistency with
+// {add,sub,mul,div}ss. In the future, when the PNaCl ABI allows
+// addpd, etc., we can use the Ty parameter to decide on adding
+// a 0x66 prefix.
+void AssemblerX8632::addps(Type /* Ty */, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x58);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::addps(Type /* Ty */, XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x58);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::subps(Type /* Ty */, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x5C);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::subps(Type /* Ty */, XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x5C);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::divps(Type /* Ty */, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x5E);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::divps(Type /* Ty */, XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x5E);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::mulps(Type /* Ty */, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x59);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::mulps(Type /* Ty */, XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x59);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::minps(XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x5D);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::maxps(XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x5F);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::andps(XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x54);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::andps(XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x54);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::orps(XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x56);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::blendvps(Type /* Ty */, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x38);
+ emitUint8(0x14);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::blendvps(Type /* Ty */, XmmRegister dst,
+ const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x38);
+ emitUint8(0x14);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::pblendvb(Type /* Ty */, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x38);
+ emitUint8(0x10);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::pblendvb(Type /* Ty */, XmmRegister dst,
+ const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x38);
+ emitUint8(0x10);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::cmpps(XmmRegister dst, XmmRegister src,
+ CondX86::CmppsCond CmpCondition) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0xC2);
+ emitXmmRegisterOperand(dst, src);
+ emitUint8(CmpCondition);
+}
+
+void AssemblerX8632::cmpps(XmmRegister dst, const Address &src,
+ CondX86::CmppsCond CmpCondition) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0xC2);
+ emitOperand(dst, src);
+ emitUint8(CmpCondition);
+}
+
+void AssemblerX8632::sqrtps(XmmRegister dst) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x51);
+ emitXmmRegisterOperand(dst, dst);
+}
+
+void AssemblerX8632::rsqrtps(XmmRegister dst) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x52);
+ emitXmmRegisterOperand(dst, dst);
+}
+
+void AssemblerX8632::reciprocalps(XmmRegister dst) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x53);
+ emitXmmRegisterOperand(dst, dst);
+}
+
+void AssemblerX8632::movhlps(XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x12);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::movlhps(XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x16);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::unpcklps(XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x14);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::unpckhps(XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x15);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::unpcklpd(XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x14);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::unpckhpd(XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x15);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::set1ps(XmmRegister dst, GPRRegister tmp1,
+ const Immediate &imm) {
+ // Load 32-bit immediate value into tmp1.
+ mov(IceType_i32, tmp1, imm);
+ // Move value from tmp1 into dst.
+ movd(dst, tmp1);
+ // Broadcast low lane into other three lanes.
+ shufps(dst, dst, Immediate(0x0));
+}
+
+void AssemblerX8632::shufps(XmmRegister dst, XmmRegister src,
+ const Immediate &imm) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0xC6);
+ emitXmmRegisterOperand(dst, src);
+ assert(imm.is_uint8());
+ emitUint8(imm.value());
+}
+
+void AssemblerX8632::pshufd(Type /* Ty */, XmmRegister dst, XmmRegister src,
+ const Immediate &imm) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x70);
+ emitXmmRegisterOperand(dst, src);
+ assert(imm.is_uint8());
+ emitUint8(imm.value());
+}
+
+void AssemblerX8632::pshufd(Type /* Ty */, XmmRegister dst, const Address &src,
+ const Immediate &imm) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x70);
+ emitOperand(dst, src);
+ assert(imm.is_uint8());
+ emitUint8(imm.value());
+}
+
+void AssemblerX8632::shufps(Type /* Ty */, XmmRegister dst, XmmRegister src,
+ const Immediate &imm) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0xC6);
+ emitXmmRegisterOperand(dst, src);
+ assert(imm.is_uint8());
+ emitUint8(imm.value());
+}
+
+void AssemblerX8632::shufps(Type /* Ty */, XmmRegister dst, const Address &src,
+ const Immediate &imm) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0xC6);
+ emitOperand(dst, src);
+ assert(imm.is_uint8());
+ emitUint8(imm.value());
+}
+
+void AssemblerX8632::minpd(XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x5D);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::maxpd(XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x5F);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::sqrtpd(XmmRegister dst) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x51);
+ emitXmmRegisterOperand(dst, dst);
+}
+
+void AssemblerX8632::shufpd(XmmRegister dst, XmmRegister src,
+ const Immediate &imm) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0xC6);
+ emitXmmRegisterOperand(dst, src);
+ assert(imm.is_uint8());
+ emitUint8(imm.value());
+}
+
+void AssemblerX8632::cvtdq2ps(Type /* Ignore */, XmmRegister dst,
+ XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x5B);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::cvtdq2ps(Type /* Ignore */, XmmRegister dst,
+ const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x5B);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::cvttps2dq(Type /* Ignore */, XmmRegister dst,
+ XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xF3);
+ emitUint8(0x0F);
+ emitUint8(0x5B);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::cvttps2dq(Type /* Ignore */, XmmRegister dst,
+ const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xF3);
+ emitUint8(0x0F);
+ emitUint8(0x5B);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::cvtsi2ss(Type DestTy, XmmRegister dst, GPRRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(isFloat32Asserting32Or64(DestTy) ? 0xF3 : 0xF2);
+ emitUint8(0x0F);
+ emitUint8(0x2A);
+ emitRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::cvtsi2ss(Type DestTy, XmmRegister dst,
+ const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(isFloat32Asserting32Or64(DestTy) ? 0xF3 : 0xF2);
+ emitUint8(0x0F);
+ emitUint8(0x2A);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::cvtfloat2float(Type SrcTy, XmmRegister dst,
+ XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ // ss2sd or sd2ss
+ emitUint8(isFloat32Asserting32Or64(SrcTy) ? 0xF3 : 0xF2);
+ emitUint8(0x0F);
+ emitUint8(0x5A);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::cvtfloat2float(Type SrcTy, XmmRegister dst,
+ const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(isFloat32Asserting32Or64(SrcTy) ? 0xF3 : 0xF2);
+ emitUint8(0x0F);
+ emitUint8(0x5A);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::cvttss2si(Type SrcTy, GPRRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(isFloat32Asserting32Or64(SrcTy) ? 0xF3 : 0xF2);
+ emitUint8(0x0F);
+ emitUint8(0x2C);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::cvttss2si(Type SrcTy, GPRRegister dst,
+ const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(isFloat32Asserting32Or64(SrcTy) ? 0xF3 : 0xF2);
+ emitUint8(0x0F);
+ emitUint8(0x2C);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::ucomiss(Type Ty, XmmRegister a, XmmRegister b) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_f64)
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x2E);
+ emitXmmRegisterOperand(a, b);
+}
+
+void AssemblerX8632::ucomiss(Type Ty, XmmRegister a, const Address &b) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_f64)
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x2E);
+ emitOperand(a, b);
+}
+
+void AssemblerX8632::movmskpd(GPRRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x50);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::movmskps(GPRRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x50);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::sqrtss(Type Ty, XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
+ emitUint8(0x0F);
+ emitUint8(0x51);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::sqrtss(Type Ty, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
+ emitUint8(0x0F);
+ emitUint8(0x51);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::xorpd(XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x57);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::xorpd(XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x57);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::orpd(XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x56);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::xorps(XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x57);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::xorps(XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x57);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::andpd(XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x54);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::andpd(XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x54);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::insertps(Type Ty, XmmRegister dst, XmmRegister src,
+ const Immediate &imm) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(imm.is_uint8());
+ assert(isVectorFloatingType(Ty));
+ (void)Ty;
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x3A);
+ emitUint8(0x21);
+ emitXmmRegisterOperand(dst, src);
+ emitUint8(imm.value());
+}
+
+void AssemblerX8632::insertps(Type Ty, XmmRegister dst, const Address &src,
+ const Immediate &imm) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(imm.is_uint8());
+ assert(isVectorFloatingType(Ty));
+ (void)Ty;
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x3A);
+ emitUint8(0x21);
+ emitOperand(dst, src);
+ emitUint8(imm.value());
+}
+
+void AssemblerX8632::pinsr(Type Ty, XmmRegister dst, GPRRegister src,
+ const Immediate &imm) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(imm.is_uint8());
+ if (Ty == IceType_i16) {
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0xC4);
+ emitXmmRegisterOperand(dst, XmmRegister(src));
+ emitUint8(imm.value());
+ } else {
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x3A);
+ emitUint8(isByteSizedType(Ty) ? 0x20 : 0x22);
+ emitXmmRegisterOperand(dst, XmmRegister(src));
+ emitUint8(imm.value());
+ }
+}
+
+void AssemblerX8632::pinsr(Type Ty, XmmRegister dst, const Address &src,
+ const Immediate &imm) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(imm.is_uint8());
+ if (Ty == IceType_i16) {
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0xC4);
+ emitOperand(dst, src);
+ emitUint8(imm.value());
+ } else {
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x3A);
+ emitUint8(isByteSizedType(Ty) ? 0x20 : 0x22);
+ emitOperand(dst, src);
+ emitUint8(imm.value());
+ }
+}
+
+void AssemblerX8632::pextr(Type Ty, GPRRegister dst, XmmRegister src,
+ const Immediate &imm) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(imm.is_uint8());
+ if (Ty == IceType_i16) {
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0xC5);
+ emitXmmRegisterOperand(XmmRegister(dst), src);
+ emitUint8(imm.value());
+ } else {
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x3A);
+ emitUint8(isByteSizedType(Ty) ? 0x14 : 0x16);
+ // SSE 4.1 versions are "MRI" because dst can be mem, while
+ // pextrw (SSE2) is RMI because dst must be reg.
+ emitXmmRegisterOperand(src, XmmRegister(dst));
+ emitUint8(imm.value());
+ }
+}
+
+void AssemblerX8632::pmovsxdq(XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x38);
+ emitUint8(0x25);
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::pcmpeq(Type Ty, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ if (isByteSizedArithType(Ty)) {
+ emitUint8(0x74);
+ } else if (Ty == IceType_i16) {
+ emitUint8(0x75);
+ } else {
+ emitUint8(0x76);
+ }
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::pcmpeq(Type Ty, XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ if (isByteSizedArithType(Ty)) {
+ emitUint8(0x74);
+ } else if (Ty == IceType_i16) {
+ emitUint8(0x75);
+ } else {
+ emitUint8(0x76);
+ }
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::pcmpgt(Type Ty, XmmRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ if (isByteSizedArithType(Ty)) {
+ emitUint8(0x64);
+ } else if (Ty == IceType_i16) {
+ emitUint8(0x65);
+ } else {
+ emitUint8(0x66);
+ }
+ emitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::pcmpgt(Type Ty, XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ if (isByteSizedArithType(Ty)) {
+ emitUint8(0x64);
+ } else if (Ty == IceType_i16) {
+ emitUint8(0x65);
+ } else {
+ emitUint8(0x66);
+ }
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::roundsd(XmmRegister dst, XmmRegister src,
+ RoundingMode mode) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x3A);
+ emitUint8(0x0B);
+ emitXmmRegisterOperand(dst, src);
+ // Mask precision exeption.
+ emitUint8(static_cast<uint8_t>(mode) | 0x8);
+}
+
+void AssemblerX8632::fnstcw(const Address &dst) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xD9);
+ emitOperand(7, dst);
+}
+
+void AssemblerX8632::fldcw(const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xD9);
+ emitOperand(5, src);
+}
+
+void AssemblerX8632::fistpl(const Address &dst) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xDF);
+ emitOperand(7, dst);
+}
+
+void AssemblerX8632::fistps(const Address &dst) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xDB);
+ emitOperand(3, dst);
+}
+
+void AssemblerX8632::fildl(const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xDF);
+ emitOperand(5, src);
+}
+
+void AssemblerX8632::filds(const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xDB);
+ emitOperand(0, src);
+}
+
+void AssemblerX8632::fincstp() {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xD9);
+ emitUint8(0xF7);
+}
+
+template <uint32_t Tag>
+void AssemblerX8632::arith_int(Type Ty, GPRRegister reg, const Immediate &imm) {
+ static_assert(Tag < 8, "Tag must be between 0..7");
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (isByteSizedType(Ty)) {
+ emitComplexI8(Tag, Operand(reg), imm);
+ return;
+ }
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ emitComplex(Ty, Tag, Operand(reg), imm);
+}
+
+template <uint32_t Tag>
+void AssemblerX8632::arith_int(Type Ty, GPRRegister reg0, GPRRegister reg1) {
+ static_assert(Tag < 8, "Tag must be between 0..7");
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (isByteSizedType(Ty))
+ emitUint8(Tag * 8 + 2);
+ else
+ emitUint8(Tag * 8 + 3);
+ emitRegisterOperand(reg0, reg1);
+}
+
+template <uint32_t Tag>
+void AssemblerX8632::arith_int(Type Ty, GPRRegister reg,
+ const Address &address) {
+ static_assert(Tag < 8, "Tag must be between 0..7");
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (isByteSizedType(Ty))
+ emitUint8(Tag * 8 + 2);
+ else
+ emitUint8(Tag * 8 + 3);
+ emitOperand(reg, address);
+}
+
+template <uint32_t Tag>
+void AssemblerX8632::arith_int(Type Ty, const Address &address,
+ GPRRegister reg) {
+ static_assert(Tag < 8, "Tag must be between 0..7");
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (isByteSizedType(Ty))
+ emitUint8(Tag * 8 + 0);
+ else
+ emitUint8(Tag * 8 + 1);
+ emitOperand(reg, address);
+}
+
+template <uint32_t Tag>
+void AssemblerX8632::arith_int(Type Ty, const Address &address,
+ const Immediate &imm) {
+ static_assert(Tag < 8, "Tag must be between 0..7");
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (isByteSizedType(Ty)) {
+ emitComplexI8(Tag, address, imm);
+ return;
+ }
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ emitComplex(Ty, Tag, address, imm);
+}
+
+void AssemblerX8632::cmp(Type Ty, GPRRegister reg, const Immediate &imm) {
+ arith_int<7>(Ty, reg, imm);
+}
+
+void AssemblerX8632::cmp(Type Ty, GPRRegister reg0, GPRRegister reg1) {
+ arith_int<7>(Ty, reg0, reg1);
+}
+
+void AssemblerX8632::cmp(Type Ty, GPRRegister reg, const Address &address) {
+ arith_int<7>(Ty, reg, address);
+}
+
+void AssemblerX8632::cmp(Type Ty, const Address &address, GPRRegister reg) {
+ arith_int<7>(Ty, address, reg);
+}
+
+void AssemblerX8632::cmp(Type Ty, const Address &address,
+ const Immediate &imm) {
+ arith_int<7>(Ty, address, imm);
+}
+
+void AssemblerX8632::test(Type Ty, GPRRegister reg1, GPRRegister reg2) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (isByteSizedType(Ty))
+ emitUint8(0x84);
+ else
+ emitUint8(0x85);
+ emitRegisterOperand(reg1, reg2);
+}
+
+void AssemblerX8632::test(Type Ty, const Address &addr, GPRRegister reg) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (isByteSizedType(Ty))
+ emitUint8(0x84);
+ else
+ emitUint8(0x85);
+ emitOperand(reg, addr);
+}
+
+void AssemblerX8632::test(Type Ty, GPRRegister reg,
+ const Immediate &immediate) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ // For registers that have a byte variant (EAX, EBX, ECX, and EDX)
+ // we only test the byte register to keep the encoding short.
+ // This is legal even if the register had high bits set since
+ // this only sets flags registers based on the "AND" of the two operands,
+ // and the immediate had zeros at those high bits.
+ if (immediate.is_uint8() && reg < 4) {
+ // Use zero-extended 8-bit immediate.
+ if (reg == RegX8632::Encoded_Reg_eax) {
+ emitUint8(0xA8);
+ } else {
+ emitUint8(0xF6);
+ emitUint8(0xC0 + reg);
+ }
+ emitUint8(immediate.value() & 0xFF);
+ } else if (reg == RegX8632::Encoded_Reg_eax) {
+ // Use short form if the destination is EAX.
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ emitUint8(0xA9);
+ emitImmediate(Ty, immediate);
+ } else {
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ emitUint8(0xF7);
+ emitRegisterOperand(0, reg);
+ emitImmediate(Ty, immediate);
+ }
+}
+
+void AssemblerX8632::test(Type Ty, const Address &addr,
+ const Immediate &immediate) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ // If the immediate is short, we only test the byte addr to keep the
+ // encoding short.
+ if (immediate.is_uint8()) {
+ // Use zero-extended 8-bit immediate.
+ emitUint8(0xF6);
+ emitOperand(0, addr);
+ emitUint8(immediate.value() & 0xFF);
+ } else {
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ emitUint8(0xF7);
+ emitOperand(0, addr);
+ emitImmediate(Ty, immediate);
+ }
+}
+
+void AssemblerX8632::And(Type Ty, GPRRegister dst, GPRRegister src) {
+ arith_int<4>(Ty, dst, src);
+}
+
+void AssemblerX8632::And(Type Ty, GPRRegister dst, const Address &address) {
+ arith_int<4>(Ty, dst, address);
+}
+
+void AssemblerX8632::And(Type Ty, GPRRegister dst, const Immediate &imm) {
+ arith_int<4>(Ty, dst, imm);
+}
+
+void AssemblerX8632::And(Type Ty, const Address &address, GPRRegister reg) {
+ arith_int<4>(Ty, address, reg);
+}
+
+void AssemblerX8632::And(Type Ty, const Address &address,
+ const Immediate &imm) {
+ arith_int<4>(Ty, address, imm);
+}
+
+void AssemblerX8632::Or(Type Ty, GPRRegister dst, GPRRegister src) {
+ arith_int<1>(Ty, dst, src);
+}
+
+void AssemblerX8632::Or(Type Ty, GPRRegister dst, const Address &address) {
+ arith_int<1>(Ty, dst, address);
+}
+
+void AssemblerX8632::Or(Type Ty, GPRRegister dst, const Immediate &imm) {
+ arith_int<1>(Ty, dst, imm);
+}
+
+void AssemblerX8632::Or(Type Ty, const Address &address, GPRRegister reg) {
+ arith_int<1>(Ty, address, reg);
+}
+
+void AssemblerX8632::Or(Type Ty, const Address &address, const Immediate &imm) {
+ arith_int<1>(Ty, address, imm);
+}
+
+void AssemblerX8632::Xor(Type Ty, GPRRegister dst, GPRRegister src) {
+ arith_int<6>(Ty, dst, src);
+}
+
+void AssemblerX8632::Xor(Type Ty, GPRRegister dst, const Address &address) {
+ arith_int<6>(Ty, dst, address);
+}
+
+void AssemblerX8632::Xor(Type Ty, GPRRegister dst, const Immediate &imm) {
+ arith_int<6>(Ty, dst, imm);
+}
+
+void AssemblerX8632::Xor(Type Ty, const Address &address, GPRRegister reg) {
+ arith_int<6>(Ty, address, reg);
+}
+
+void AssemblerX8632::Xor(Type Ty, const Address &address,
+ const Immediate &imm) {
+ arith_int<6>(Ty, address, imm);
+}
+
+void AssemblerX8632::add(Type Ty, GPRRegister dst, GPRRegister src) {
+ arith_int<0>(Ty, dst, src);
+}
+
+void AssemblerX8632::add(Type Ty, GPRRegister reg, const Address &address) {
+ arith_int<0>(Ty, reg, address);
+}
+
+void AssemblerX8632::add(Type Ty, GPRRegister reg, const Immediate &imm) {
+ arith_int<0>(Ty, reg, imm);
+}
+
+void AssemblerX8632::add(Type Ty, const Address &address, GPRRegister reg) {
+ arith_int<0>(Ty, address, reg);
+}
+
+void AssemblerX8632::add(Type Ty, const Address &address,
+ const Immediate &imm) {
+ arith_int<0>(Ty, address, imm);
+}
+
+void AssemblerX8632::adc(Type Ty, GPRRegister dst, GPRRegister src) {
+ arith_int<2>(Ty, dst, src);
+}
+
+void AssemblerX8632::adc(Type Ty, GPRRegister dst, const Address &address) {
+ arith_int<2>(Ty, dst, address);
+}
+
+void AssemblerX8632::adc(Type Ty, GPRRegister reg, const Immediate &imm) {
+ arith_int<2>(Ty, reg, imm);
+}
+
+void AssemblerX8632::adc(Type Ty, const Address &address, GPRRegister reg) {
+ arith_int<2>(Ty, address, reg);
+}
+
+void AssemblerX8632::adc(Type Ty, const Address &address,
+ const Immediate &imm) {
+ arith_int<2>(Ty, address, imm);
+}
+
+void AssemblerX8632::sub(Type Ty, GPRRegister dst, GPRRegister src) {
+ arith_int<5>(Ty, dst, src);
+}
+
+void AssemblerX8632::sub(Type Ty, GPRRegister reg, const Address &address) {
+ arith_int<5>(Ty, reg, address);
+}
+
+void AssemblerX8632::sub(Type Ty, GPRRegister reg, const Immediate &imm) {
+ arith_int<5>(Ty, reg, imm);
+}
+
+void AssemblerX8632::sub(Type Ty, const Address &address, GPRRegister reg) {
+ arith_int<5>(Ty, address, reg);
+}
+
+void AssemblerX8632::sub(Type Ty, const Address &address,
+ const Immediate &imm) {
+ arith_int<5>(Ty, address, imm);
+}
+
+void AssemblerX8632::sbb(Type Ty, GPRRegister dst, GPRRegister src) {
+ arith_int<3>(Ty, dst, src);
+}
+
+void AssemblerX8632::sbb(Type Ty, GPRRegister dst, const Address &address) {
+ arith_int<3>(Ty, dst, address);
+}
+
+void AssemblerX8632::sbb(Type Ty, GPRRegister reg, const Immediate &imm) {
+ arith_int<3>(Ty, reg, imm);
+}
+
+void AssemblerX8632::sbb(Type Ty, const Address &address, GPRRegister reg) {
+ arith_int<3>(Ty, address, reg);
+}
+
+void AssemblerX8632::sbb(Type Ty, const Address &address,
+ const Immediate &imm) {
+ arith_int<3>(Ty, address, imm);
+}
+
+void AssemblerX8632::cbw() {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitOperandSizeOverride();
+ emitUint8(0x98);
+}
+
+void AssemblerX8632::cwd() {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitOperandSizeOverride();
+ emitUint8(0x99);
+}
+
+void AssemblerX8632::cdq() {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x99);
+}
+
+void AssemblerX8632::div(Type Ty, GPRRegister reg) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (isByteSizedArithType(Ty))
+ emitUint8(0xF6);
+ else
+ emitUint8(0xF7);
+ emitRegisterOperand(6, reg);
+}
+
+void AssemblerX8632::div(Type Ty, const Address &addr) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (isByteSizedArithType(Ty))
+ emitUint8(0xF6);
+ else
+ emitUint8(0xF7);
+ emitOperand(6, addr);
+}
+
+void AssemblerX8632::idiv(Type Ty, GPRRegister reg) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (isByteSizedArithType(Ty))
+ emitUint8(0xF6);
+ else
+ emitUint8(0xF7);
+ emitRegisterOperand(7, reg);
+}
+
+void AssemblerX8632::idiv(Type Ty, const Address &addr) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (isByteSizedArithType(Ty))
+ emitUint8(0xF6);
+ else
+ emitUint8(0xF7);
+ emitOperand(7, addr);
+}
+
+void AssemblerX8632::imul(Type Ty, GPRRegister dst, GPRRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(Ty == IceType_i16 || Ty == IceType_i32);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ emitUint8(0x0F);
+ emitUint8(0xAF);
+ emitRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::imul(Type Ty, GPRRegister reg, const Address &address) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(Ty == IceType_i16 || Ty == IceType_i32);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ emitUint8(0x0F);
+ emitUint8(0xAF);
+ emitOperand(reg, address);
+}
+
+void AssemblerX8632::imul(Type Ty, GPRRegister reg, const Immediate &imm) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(Ty == IceType_i16 || Ty == IceType_i32);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (imm.is_int8()) {
+ emitUint8(0x6B);
+ emitRegisterOperand(reg, reg);
+ emitUint8(imm.value() & 0xFF);
+ } else {
+ emitUint8(0x69);
+ emitRegisterOperand(reg, reg);
+ emitImmediate(Ty, imm);
+ }
+}
+
+void AssemblerX8632::imul(Type Ty, GPRRegister reg) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (isByteSizedArithType(Ty))
+ emitUint8(0xF6);
+ else
+ emitUint8(0xF7);
+ emitRegisterOperand(5, reg);
+}
+
+void AssemblerX8632::imul(Type Ty, const Address &address) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (isByteSizedArithType(Ty))
+ emitUint8(0xF6);
+ else
+ emitUint8(0xF7);
+ emitOperand(5, address);
+}
+
+void AssemblerX8632::mul(Type Ty, GPRRegister reg) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (isByteSizedArithType(Ty))
+ emitUint8(0xF6);
+ else
+ emitUint8(0xF7);
+ emitRegisterOperand(4, reg);
+}
+
+void AssemblerX8632::mul(Type Ty, const Address &address) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (isByteSizedArithType(Ty))
+ emitUint8(0xF6);
+ else
+ emitUint8(0xF7);
+ emitOperand(4, address);
+}
+
+void AssemblerX8632::incl(GPRRegister reg) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x40 + reg);
+}
+
+void AssemblerX8632::incl(const Address &address) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xFF);
+ emitOperand(0, address);
+}
+
+void AssemblerX8632::decl(GPRRegister reg) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x48 + reg);
+}
+
+void AssemblerX8632::decl(const Address &address) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xFF);
+ emitOperand(1, address);
+}
+
+void AssemblerX8632::rol(Type Ty, GPRRegister reg, const Immediate &imm) {
+ emitGenericShift(0, Ty, reg, imm);
+}
+
+void AssemblerX8632::rol(Type Ty, GPRRegister operand, GPRRegister shifter) {
+ emitGenericShift(0, Ty, Operand(operand), shifter);
+}
+
+void AssemblerX8632::rol(Type Ty, const Address &operand, GPRRegister shifter) {
+ emitGenericShift(0, Ty, operand, shifter);
+}
+
+void AssemblerX8632::shl(Type Ty, GPRRegister reg, const Immediate &imm) {
+ emitGenericShift(4, Ty, reg, imm);
+}
+
+void AssemblerX8632::shl(Type Ty, GPRRegister operand, GPRRegister shifter) {
+ emitGenericShift(4, Ty, Operand(operand), shifter);
+}
+
+void AssemblerX8632::shl(Type Ty, const Address &operand, GPRRegister shifter) {
+ emitGenericShift(4, Ty, operand, shifter);
+}
+
+void AssemblerX8632::shr(Type Ty, GPRRegister reg, const Immediate &imm) {
+ emitGenericShift(5, Ty, reg, imm);
+}
+
+void AssemblerX8632::shr(Type Ty, GPRRegister operand, GPRRegister shifter) {
+ emitGenericShift(5, Ty, Operand(operand), shifter);
+}
+
+void AssemblerX8632::shr(Type Ty, const Address &operand, GPRRegister shifter) {
+ emitGenericShift(5, Ty, operand, shifter);
+}
+
+void AssemblerX8632::sar(Type Ty, GPRRegister reg, const Immediate &imm) {
+ emitGenericShift(7, Ty, reg, imm);
+}
+
+void AssemblerX8632::sar(Type Ty, GPRRegister operand, GPRRegister shifter) {
+ emitGenericShift(7, Ty, Operand(operand), shifter);
+}
+
+void AssemblerX8632::sar(Type Ty, const Address &address, GPRRegister shifter) {
+ emitGenericShift(7, Ty, address, shifter);
+}
+
+void AssemblerX8632::shld(Type Ty, GPRRegister dst, GPRRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(Ty == IceType_i16 || Ty == IceType_i32);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ emitUint8(0x0F);
+ emitUint8(0xA5);
+ emitRegisterOperand(src, dst);
+}
+
+void AssemblerX8632::shld(Type Ty, GPRRegister dst, GPRRegister src,
+ const Immediate &imm) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(Ty == IceType_i16 || Ty == IceType_i32);
+ assert(imm.is_int8());
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ emitUint8(0x0F);
+ emitUint8(0xA4);
+ emitRegisterOperand(src, dst);
+ emitUint8(imm.value() & 0xFF);
+}
+
+void AssemblerX8632::shld(Type Ty, const Address &operand, GPRRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(Ty == IceType_i16 || Ty == IceType_i32);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ emitUint8(0x0F);
+ emitUint8(0xA5);
+ emitOperand(src, operand);
+}
+
+void AssemblerX8632::shrd(Type Ty, GPRRegister dst, GPRRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(Ty == IceType_i16 || Ty == IceType_i32);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ emitUint8(0x0F);
+ emitUint8(0xAD);
+ emitRegisterOperand(src, dst);
+}
+
+void AssemblerX8632::shrd(Type Ty, GPRRegister dst, GPRRegister src,
+ const Immediate &imm) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(Ty == IceType_i16 || Ty == IceType_i32);
+ assert(imm.is_int8());
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ emitUint8(0x0F);
+ emitUint8(0xAC);
+ emitRegisterOperand(src, dst);
+ emitUint8(imm.value() & 0xFF);
+}
+
+void AssemblerX8632::shrd(Type Ty, const Address &dst, GPRRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(Ty == IceType_i16 || Ty == IceType_i32);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ emitUint8(0x0F);
+ emitUint8(0xAD);
+ emitOperand(src, dst);
+}
+
+void AssemblerX8632::neg(Type Ty, GPRRegister reg) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (isByteSizedArithType(Ty))
+ emitUint8(0xF6);
+ else
+ emitUint8(0xF7);
+ emitRegisterOperand(3, reg);
+}
+
+void AssemblerX8632::neg(Type Ty, const Address &addr) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (isByteSizedArithType(Ty))
+ emitUint8(0xF6);
+ else
+ emitUint8(0xF7);
+ emitOperand(3, addr);
+}
+
+void AssemblerX8632::notl(GPRRegister reg) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xF7);
+ emitUint8(0xD0 | reg);
+}
+
+void AssemblerX8632::bswap(Type Ty, GPRRegister reg) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(Ty == IceType_i32);
+ (void)Ty;
+ emitUint8(0x0F);
+ emitUint8(0xC8 | reg);
+}
+
+void AssemblerX8632::bsf(Type Ty, GPRRegister dst, GPRRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(Ty == IceType_i16 || Ty == IceType_i32);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ emitUint8(0x0F);
+ emitUint8(0xBC);
+ emitRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::bsf(Type Ty, GPRRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(Ty == IceType_i16 || Ty == IceType_i32);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ emitUint8(0x0F);
+ emitUint8(0xBC);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::bsr(Type Ty, GPRRegister dst, GPRRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(Ty == IceType_i16 || Ty == IceType_i32);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ emitUint8(0x0F);
+ emitUint8(0xBD);
+ emitRegisterOperand(dst, src);
+}
+
+void AssemblerX8632::bsr(Type Ty, GPRRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(Ty == IceType_i16 || Ty == IceType_i32);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ emitUint8(0x0F);
+ emitUint8(0xBD);
+ emitOperand(dst, src);
+}
+
+void AssemblerX8632::bt(GPRRegister base, GPRRegister offset) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0xA3);
+ emitRegisterOperand(offset, base);
+}
+
+void AssemblerX8632::ret() {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xC3);
+}
+
+void AssemblerX8632::ret(const Immediate &imm) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xC2);
+ assert(imm.is_uint16());
+ emitUint8(imm.value() & 0xFF);
+ emitUint8((imm.value() >> 8) & 0xFF);
+}
+
+void AssemblerX8632::nop(int size) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ // There are nops up to size 15, but for now just provide up to size 8.
+ assert(0 < size && size <= MAX_NOP_SIZE);
+ switch (size) {
+ case 1:
+ emitUint8(0x90);
+ break;
+ case 2:
+ emitUint8(0x66);
+ emitUint8(0x90);
+ break;
+ case 3:
+ emitUint8(0x0F);
+ emitUint8(0x1F);
+ emitUint8(0x00);
+ break;
+ case 4:
+ emitUint8(0x0F);
+ emitUint8(0x1F);
+ emitUint8(0x40);
+ emitUint8(0x00);
+ break;
+ case 5:
+ emitUint8(0x0F);
+ emitUint8(0x1F);
+ emitUint8(0x44);
+ emitUint8(0x00);
+ emitUint8(0x00);
+ break;
+ case 6:
+ emitUint8(0x66);
+ emitUint8(0x0F);
+ emitUint8(0x1F);
+ emitUint8(0x44);
+ emitUint8(0x00);
+ emitUint8(0x00);
+ break;
+ case 7:
+ emitUint8(0x0F);
+ emitUint8(0x1F);
+ emitUint8(0x80);
+ emitUint8(0x00);
+ emitUint8(0x00);
+ emitUint8(0x00);
+ emitUint8(0x00);
+ break;
+ case 8:
+ emitUint8(0x0F);
+ emitUint8(0x1F);
+ emitUint8(0x84);
+ emitUint8(0x00);
+ emitUint8(0x00);
+ emitUint8(0x00);
+ emitUint8(0x00);
+ emitUint8(0x00);
+ break;
+ default:
+ llvm_unreachable("Unimplemented");
+ }
+}
+
+void AssemblerX8632::int3() {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xCC);
+}
+
+void AssemblerX8632::hlt() {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xF4);
+}
+
+void AssemblerX8632::ud2() {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x0B);
+}
+
+void AssemblerX8632::j(CondX86::BrCond condition, Label *label, bool near) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (label->IsBound()) {
+ static const int kShortSize = 2;
+ static const int kLongSize = 6;
+ intptr_t offset = label->Position() - Buffer.size();
+ assert(offset <= 0);
+ if (Utils::IsInt(8, offset - kShortSize)) {
+ // TODO(stichnot): Here and in jmp(), we may need to be more
+ // conservative about the backward branch distance if the branch
+ // instruction is within a bundle_lock sequence, because the
+ // distance may increase when padding is added. This isn't an
+ // issue for branches outside a bundle_lock, because if padding
+ // is added, the retry may change it to a long backward branch
+ // without affecting any of the bookkeeping.
+ emitUint8(0x70 + condition);
+ emitUint8((offset - kShortSize) & 0xFF);
+ } else {
+ emitUint8(0x0F);
+ emitUint8(0x80 + condition);
+ emitInt32(offset - kLongSize);
+ }
+ } else if (near) {
+ emitUint8(0x70 + condition);
+ emitNearLabelLink(label);
+ } else {
+ emitUint8(0x0F);
+ emitUint8(0x80 + condition);
+ emitLabelLink(label);
+ }
+}
+
+void AssemblerX8632::j(CondX86::BrCond condition,
+ const ConstantRelocatable *label) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0x80 + condition);
+ emitFixup(this->createFixup(llvm::ELF::R_386_PC32, label));
+ emitInt32(-4);
+}
+
+void AssemblerX8632::jmp(GPRRegister reg) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xFF);
+ emitRegisterOperand(4, reg);
+}
+
+void AssemblerX8632::jmp(Label *label, bool near) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (label->IsBound()) {
+ static const int kShortSize = 2;
+ static const int kLongSize = 5;
+ intptr_t offset = label->Position() - Buffer.size();
+ assert(offset <= 0);
+ if (Utils::IsInt(8, offset - kShortSize)) {
+ emitUint8(0xEB);
+ emitUint8((offset - kShortSize) & 0xFF);
+ } else {
+ emitUint8(0xE9);
+ emitInt32(offset - kLongSize);
+ }
+ } else if (near) {
+ emitUint8(0xEB);
+ emitNearLabelLink(label);
+ } else {
+ emitUint8(0xE9);
+ emitLabelLink(label);
+ }
+}
+
+void AssemblerX8632::jmp(const ConstantRelocatable *label) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xE9);
+ emitFixup(this->createFixup(llvm::ELF::R_386_PC32, label));
+ emitInt32(-4);
+}
+
+void AssemblerX8632::mfence() {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0x0F);
+ emitUint8(0xAE);
+ emitUint8(0xF0);
+}
+
+void AssemblerX8632::lock() {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(0xF0);
+}
+
+void AssemblerX8632::cmpxchg(Type Ty, const Address &address, GPRRegister reg,
+ bool Locked) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (Locked)
+ emitUint8(0xF0);
+ emitUint8(0x0F);
+ if (isByteSizedArithType(Ty))
+ emitUint8(0xB0);
+ else
+ emitUint8(0xB1);
+ emitOperand(reg, address);
+}
+
+void AssemblerX8632::cmpxchg8b(const Address &address, bool Locked) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Locked)
+ emitUint8(0xF0);
+ emitUint8(0x0F);
+ emitUint8(0xC7);
+ emitOperand(1, address);
+}
+
+void AssemblerX8632::xadd(Type Ty, const Address &addr, GPRRegister reg,
+ bool Locked) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (Locked)
+ emitUint8(0xF0);
+ emitUint8(0x0F);
+ if (isByteSizedArithType(Ty))
+ emitUint8(0xC0);
+ else
+ emitUint8(0xC1);
+ emitOperand(reg, addr);
+}
+
+void AssemblerX8632::xchg(Type Ty, const Address &addr, GPRRegister reg) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (isByteSizedArithType(Ty))
+ emitUint8(0x86);
+ else
+ emitUint8(0x87);
+ emitOperand(reg, addr);
+}
+
+void AssemblerX8632::emitSegmentOverride(uint8_t prefix) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ emitUint8(prefix);
+}
+
+void AssemblerX8632::align(intptr_t alignment, intptr_t offset) {
+ assert(llvm::isPowerOf2_32(alignment));
+ intptr_t pos = offset + Buffer.getPosition();
+ intptr_t mod = pos & (alignment - 1);
+ if (mod == 0) {
+ return;
+ }
+ intptr_t bytes_needed = alignment - mod;
+ while (bytes_needed > MAX_NOP_SIZE) {
+ nop(MAX_NOP_SIZE);
+ bytes_needed -= MAX_NOP_SIZE;
+ }
+ if (bytes_needed) {
+ nop(bytes_needed);
+ }
+ assert(((offset + Buffer.getPosition()) & (alignment - 1)) == 0);
+}
+
+void AssemblerX8632::bind(Label *label) {
+ intptr_t bound = Buffer.size();
+ assert(!label->IsBound()); // Labels can only be bound once.
+ while (label->IsLinked()) {
+ intptr_t position = label->LinkPosition();
+ intptr_t next = Buffer.load<int32_t>(position);
+ Buffer.store<int32_t>(position, bound - (position + 4));
+ label->position_ = next;
+ }
+ while (label->HasNear()) {
+ intptr_t position = label->NearPosition();
+ intptr_t offset = bound - (position + 1);
+ assert(Utils::IsInt(8, offset));
+ Buffer.store<int8_t>(position, offset);
+ }
+ label->BindTo(bound);
+}
+
+void AssemblerX8632::emitOperand(int rm, const Operand &operand) {
+ assert(rm >= 0 && rm < 8);
+ const intptr_t length = operand.length_;
+ assert(length > 0);
+ // Emit the ModRM byte updated with the given RM value.
+ assert((operand.encoding_[0] & 0x38) == 0);
+ emitUint8(operand.encoding_[0] + (rm << 3));
+ if (operand.fixup()) {
+ emitFixup(operand.fixup());
+ }
+ // Emit the rest of the encoded operand.
+ for (intptr_t i = 1; i < length; i++) {
+ emitUint8(operand.encoding_[i]);
+ }
+}
+
+void AssemblerX8632::emitImmediate(Type Ty, const Immediate &imm) {
+ if (Ty == IceType_i16) {
+ assert(!imm.fixup());
+ emitInt16(imm.value());
+ } else {
+ if (imm.fixup()) {
+ emitFixup(imm.fixup());
+ }
+ emitInt32(imm.value());
+ }
+}
+
+void AssemblerX8632::emitComplexI8(int rm, const Operand &operand,
+ const Immediate &immediate) {
+ assert(rm >= 0 && rm < 8);
+ assert(immediate.is_int8());
+ if (operand.IsRegister(RegX8632::Encoded_Reg_eax)) {
+ // Use short form if the destination is al.
+ emitUint8(0x04 + (rm << 3));
+ emitUint8(immediate.value() & 0xFF);
+ } else {
+ // Use sign-extended 8-bit immediate.
+ emitUint8(0x80);
+ emitOperand(rm, operand);
+ emitUint8(immediate.value() & 0xFF);
+ }
+}
+
+void AssemblerX8632::emitComplex(Type Ty, int rm, const Operand &operand,
+ const Immediate &immediate) {
+ assert(rm >= 0 && rm < 8);
+ if (immediate.is_int8()) {
+ // Use sign-extended 8-bit immediate.
+ emitUint8(0x83);
+ emitOperand(rm, operand);
+ emitUint8(immediate.value() & 0xFF);
+ } else if (operand.IsRegister(RegX8632::Encoded_Reg_eax)) {
+ // Use short form if the destination is eax.
+ emitUint8(0x05 + (rm << 3));
+ emitImmediate(Ty, immediate);
+ } else {
+ emitUint8(0x81);
+ emitOperand(rm, operand);
+ emitImmediate(Ty, immediate);
+ }
+}
+
+void AssemblerX8632::emitLabel(Label *label, intptr_t instruction_size) {
+ if (label->IsBound()) {
+ intptr_t offset = label->Position() - Buffer.size();
+ assert(offset <= 0);
+ emitInt32(offset - instruction_size);
+ } else {
+ emitLabelLink(label);
+ }
+}
+
+void AssemblerX8632::emitLabelLink(Label *Label) {
+ assert(!Label->IsBound());
+ intptr_t Position = Buffer.size();
+ emitInt32(Label->position_);
+ if (!getPreliminary())
+ Label->LinkTo(Position);
+}
+
+void AssemblerX8632::emitNearLabelLink(Label *label) {
+ assert(!label->IsBound());
+ intptr_t position = Buffer.size();
+ emitUint8(0);
+ if (!getPreliminary())
+ label->NearLinkTo(position);
+}
+
+void AssemblerX8632::emitGenericShift(int rm, Type Ty, GPRRegister reg,
+ const Immediate &imm) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(imm.is_int8());
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ if (imm.value() == 1) {
+ emitUint8(isByteSizedArithType(Ty) ? 0xD0 : 0xD1);
+ emitOperand(rm, Operand(reg));
+ } else {
+ emitUint8(isByteSizedArithType(Ty) ? 0xC0 : 0xC1);
+ emitOperand(rm, Operand(reg));
+ emitUint8(imm.value() & 0xFF);
+ }
+}
+
+void AssemblerX8632::emitGenericShift(int rm, Type Ty, const Operand &operand,
+ GPRRegister shifter) {
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ assert(shifter == RegX8632::Encoded_Reg_ecx);
+ (void)shifter;
+ if (Ty == IceType_i16)
+ emitOperandSizeOverride();
+ emitUint8(isByteSizedArithType(Ty) ? 0xD2 : 0xD3);
+ emitOperand(rm, operand);
+}
+
+} // end of namespace X8632
+} // end of namespace Ice
diff --git a/src/IceAssemblerX8632.h b/src/IceAssemblerX8632.h
index ad79489..6c22a24 100644
--- a/src/IceAssemblerX8632.h
+++ b/src/IceAssemblerX8632.h
@@ -14,9 +14,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the Assembler class for x86-32.
-//
+///
+/// \file
+/// This file implements the Assembler class for x86-32.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEASSEMBLERX8632_H
diff --git a/src/IceAssemblerX8664.cpp b/src/IceAssemblerX8664.cpp
index e56ada6..910924d 100644
--- a/src/IceAssemblerX8664.cpp
+++ b/src/IceAssemblerX8664.cpp
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the Assembler class for x86-64.
-//
+///
+/// \file
+/// This file implements the Assembler class for x86-64.
+///
//===----------------------------------------------------------------------===//
#include "IceAssemblerX8664.h"
diff --git a/src/IceAssemblerX8664.h b/src/IceAssemblerX8664.h
index 0deda30..f2ffd7f 100644
--- a/src/IceAssemblerX8664.h
+++ b/src/IceAssemblerX8664.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the Assembler class for x86-64.
-//
+///
+/// \file
+/// This file implements the Assembler class for x86-64.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEASSEMBLERX8664_H
diff --git a/src/IceBrowserCompileServer.cpp b/src/IceBrowserCompileServer.cpp
index 5a5b970..03127a9 100644
--- a/src/IceBrowserCompileServer.cpp
+++ b/src/IceBrowserCompileServer.cpp
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the browser-based compile server.
-//
+///
+/// \file
+/// This file defines the browser-based compile server.
+///
//===----------------------------------------------------------------------===//
// Can only compile this with the NaCl compiler (needs irt.h, and the
diff --git a/src/IceBrowserCompileServer.h b/src/IceBrowserCompileServer.h
index f15ddaf..e76b820 100644
--- a/src/IceBrowserCompileServer.h
+++ b/src/IceBrowserCompileServer.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the browser-specific compile server.
-//
+///
+/// \file
+/// This file declares the browser-specific compile server.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEBROWSERCOMPILESERVER_H
@@ -30,12 +31,12 @@
namespace Ice {
-// The browser variant of the compile server.
-// Compared to the commandline version, this version gets compile
-// requests over IPC. Each compile request will have a slimmed down
-// version of argc, argv while other flags are set to defaults that
-// make sense in the browser case. The output file is specified via
-// a posix FD, and input bytes are pushed to the server.
+/// The browser variant of the compile server.
+/// Compared to the commandline version, this version gets compile
+/// requests over IPC. Each compile request will have a slimmed down
+/// version of argc, argv while other flags are set to defaults that
+/// make sense in the browser case. The output file is specified via
+/// a posix FD, and input bytes are pushed to the server.
class BrowserCompileServer : public CompileServer {
BrowserCompileServer() = delete;
BrowserCompileServer(const BrowserCompileServer &) = delete;
@@ -52,21 +53,21 @@
ErrorCode &getErrorCode() final;
- // Parse and set up the flags for compile jobs.
+ /// Parse and set up the flags for compile jobs.
void getParsedFlags(uint32_t NumThreads, int argc, char **argv);
- // Creates the streams + context and starts the compile thread,
- // handing off the streams + context.
+ /// Creates the streams + context and starts the compile thread,
+ /// handing off the streams + context.
void startCompileThread(int OutFD);
- // Call to push more bytes to the current input stream.
- // Returns false on success and true on error.
+ /// Call to push more bytes to the current input stream.
+ /// Returns false on success and true on error.
bool pushInputBytes(const void *Data, size_t NumBytes);
- // Notify the input stream of EOF.
+ /// Notify the input stream of EOF.
void endInputStream();
- // Wait for the compile thread to complete then reset the state.
+ /// Wait for the compile thread to complete then reset the state.
void waitForCompileThread() {
CompileThread.join();
if (Ctx->getErrorStatus()->value())
@@ -94,12 +95,12 @@
std::string Buffer;
llvm::raw_string_ostream StrBuf;
};
- // This currently only handles a single compile request, hence one copy
- // of the state.
+ /// This currently only handles a single compile request, hence one copy
+ /// of the state.
std::unique_ptr<GlobalContext> Ctx;
- // A borrowed reference to the current InputStream. The compiler owns
- // the actual reference so the server must be careful not to access
- // after the compiler is done.
+ /// A borrowed reference to the current InputStream. The compiler owns
+ /// the actual reference so the server must be careful not to access
+ /// after the compiler is done.
llvm::QueueStreamer *InputStream = nullptr;
std::unique_ptr<Ostream> LogStream;
std::unique_ptr<llvm::raw_fd_ostream> EmitStream;
diff --git a/src/IceBuildDefs.h b/src/IceBuildDefs.h
index 6af41f1..42e66b8 100644
--- a/src/IceBuildDefs.h
+++ b/src/IceBuildDefs.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines constexpr functions to query various #define values.
-//
+///
+/// \file
+/// This file defines constexpr functions to query various #define values.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEBUILDDEFS_H
diff --git a/src/IceCfg.cpp b/src/IceCfg.cpp
index d3b0973..f7b1a8c 100644
--- a/src/IceCfg.cpp
+++ b/src/IceCfg.cpp
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the Cfg class, including constant pool
-// management.
-//
+///
+/// \file
+/// This file implements the Cfg class, including constant pool
+/// management.
+///
//===----------------------------------------------------------------------===//
#include "IceCfg.h"
diff --git a/src/IceCfg.h b/src/IceCfg.h
index 800bf40..08b4e97 100644
--- a/src/IceCfg.h
+++ b/src/IceCfg.h
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the Cfg class, which represents the control flow
-// graph and the overall per-function compilation context.
-//
+///
+/// \file
+/// This file declares the Cfg class, which represents the control flow
+/// graph and the overall per-function compilation context.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICECFG_H
@@ -35,12 +36,12 @@
uint32_t SequenceNumber) {
return std::unique_ptr<Cfg>(new Cfg(Ctx, SequenceNumber));
}
- // Gets a pointer to the current thread's Cfg.
+ /// Gets a pointer to the current thread's Cfg.
static const Cfg *getCurrentCfg() { return ICE_TLS_GET_FIELD(CurrentCfg); }
static void setCurrentCfg(const Cfg *Func) {
ICE_TLS_SET_FIELD(CurrentCfg, Func);
}
- // Gets a pointer to the current thread's Cfg's allocator.
+ /// Gets a pointer to the current thread's Cfg's allocator.
static ArenaAllocator<> *getCurrentCfgAllocator() {
assert(ICE_TLS_GET_FIELD(CurrentCfg));
return ICE_TLS_GET_FIELD(CurrentCfg)->Allocator.get();
@@ -49,44 +50,54 @@
GlobalContext *getContext() const { return Ctx; }
uint32_t getSequenceNumber() const { return SequenceNumber; }
- // Returns true if any of the specified options in the verbose mask
- // are set. If the argument is omitted, it checks if any verbose
- // options at all are set.
+ /// Returns true if any of the specified options in the verbose mask
+ /// are set. If the argument is omitted, it checks if any verbose
+ /// options at all are set.
bool isVerbose(VerboseMask Mask = IceV_All) const { return VMask & Mask; }
void setVerbose(VerboseMask Mask) { VMask = Mask; }
- // Manage the name and return type of the function being translated.
+ /// \name Manage the name and return type of the function being translated.
+ /// @{
void setFunctionName(const IceString &Name) { FunctionName = Name; }
IceString getFunctionName() const { return FunctionName; }
void setReturnType(Type Ty) { ReturnType = Ty; }
+ /// @}
- // Manage the "internal" attribute of the function.
+ /// \name Manage the "internal" attribute of the function.
+ /// @{
void setInternal(bool Internal) { IsInternalLinkage = Internal; }
bool getInternal() const { return IsInternalLinkage; }
+ /// @}
- // Translation error flagging. If support for some construct is
- // known to be missing, instead of an assertion failure, setError()
- // should be called and the error should be propagated back up.
- // This way, we can gracefully fail to translate and let a fallback
- // translator handle the function.
+ /// \name Manage errors.
+ /// @{
+
+ /// Translation error flagging. If support for some construct is
+ /// known to be missing, instead of an assertion failure, setError()
+ /// should be called and the error should be propagated back up.
+ /// This way, we can gracefully fail to translate and let a fallback
+ /// translator handle the function.
void setError(const IceString &Message);
bool hasError() const { return HasError; }
IceString getError() const { return ErrorMessage; }
+ /// @}
- // Manage nodes (a.k.a. basic blocks, CfgNodes).
+ /// \name Manage nodes (a.k.a. basic blocks, CfgNodes).
+ /// @{
void setEntryNode(CfgNode *EntryNode) { Entry = EntryNode; }
CfgNode *getEntryNode() const { return Entry; }
- // Create a node and append it to the end of the linearized list.
+ /// Create a node and append it to the end of the linearized list.
CfgNode *makeNode();
SizeT getNumNodes() const { return Nodes.size(); }
const NodeList &getNodes() const { return Nodes; }
+ /// @}
typedef int32_t IdentifierIndexType;
- // Adds a name to the list and returns its index, suitable for the
- // argument to getIdentifierName(). No checking for duplicates is
- // done. This is generally used for node names and variable names
- // to avoid embedding a std::string inside an arena-allocated
- // object.
+ /// Adds a name to the list and returns its index, suitable for the
+ /// argument to getIdentifierName(). No checking for duplicates is
+ /// done. This is generally used for node names and variable names
+ /// to avoid embedding a std::string inside an arena-allocated
+ /// object.
IdentifierIndexType addIdentifierName(const IceString &Name) {
IdentifierIndexType Index = IdentifierNames.size();
IdentifierNames.push_back(Name);
@@ -97,13 +108,17 @@
}
enum { IdentifierIndexInvalid = -1 };
- // Manage instruction numbering.
+ /// \name Manage instruction numbering.
+ /// @{
InstNumberT newInstNumber() { return NextInstNumber++; }
InstNumberT getNextInstNumber() const { return NextInstNumber; }
+ /// @}
- // Manage Variables.
- // Create a new Variable with a particular type and an optional
- // name. The Node argument is the node where the variable is defined.
+ /// \name Manage Variables.
+ /// @{
+
+ /// Create a new Variable with a particular type and an optional
+ /// name. The Node argument is the node where the variable is defined.
// TODO(jpp): untemplate this with two separate methods: makeVariable and
// makeSpillVariable.
template <typename T = Variable> T *makeVariable(Type Ty) {
@@ -114,15 +129,19 @@
}
SizeT getNumVariables() const { return Variables.size(); }
const VarList &getVariables() const { return Variables; }
+ /// @}
- // Manage arguments to the function.
+ /// \name Manage arguments to the function.
+ /// @{
void addArg(Variable *Arg);
const VarList &getArgs() const { return Args; }
VarList &getArgs() { return Args; }
void addImplicitArg(Variable *Arg);
const VarList &getImplicitArgs() const { return ImplicitArgs; }
+ /// @}
- // Miscellaneous accessors.
+ /// \name Miscellaneous accessors.
+ /// @{
TargetLowering *getTarget() const { return Target.get(); }
VariablesMetadata *getVMetadata() const { return VMetadata.get(); }
Liveness *getLiveness() const { return Live.get(); }
@@ -136,16 +155,17 @@
bool hasComputedFrame() const;
bool getFocusedTiming() const { return FocusedTiming; }
void setFocusedTiming() { FocusedTiming = true; }
+ /// @}
- // Returns true if Var is a global variable that is used by the profiling
- // code.
+ /// Returns true if Var is a global variable that is used by the profiling
+ /// code.
static bool isProfileGlobal(const VariableDeclaration &Var);
- // Passes over the CFG.
+ /// Passes over the CFG.
void translate();
- // After the CFG is fully constructed, iterate over the nodes and
- // compute the predecessor and successor edges, in the form of
- // CfgNode::InEdges[] and CfgNode::OutEdges[].
+ /// After the CFG is fully constructed, iterate over the nodes and
+ /// compute the predecessor and successor edges, in the form of
+ /// CfgNode::InEdges[] and CfgNode::OutEdges[].
void computeInOutEdges();
void renumberInstructions();
void placePhiLoads();
@@ -164,11 +184,14 @@
void contractEmptyNodes();
void doBranchOpt();
- // Manage the CurrentNode field, which is used for validating the
- // Variable::DefNode field during dumping/emitting.
+ /// \name Manage the CurrentNode field.
+ /// CurrentNode is used for validating the Variable::DefNode field during
+ /// dumping/emitting.
+ /// @{
void setCurrentNode(const CfgNode *Node) { CurrentNode = Node; }
void resetCurrentNode() { setCurrentNode(nullptr); }
const CfgNode *getCurrentNode() const { return CurrentNode; }
+ /// @}
void emit();
void emitIAS();
@@ -176,20 +199,20 @@
const Assembler *Asm);
void dump(const IceString &Message = "");
- // Allocate data of type T using the per-Cfg allocator.
+ /// Allocate data of type T using the per-Cfg allocator.
template <typename T> T *allocate() { return Allocator->Allocate<T>(); }
- // Allocate an array of data of type T using the per-Cfg allocator.
+ /// Allocate an array of data of type T using the per-Cfg allocator.
template <typename T> T *allocateArrayOf(size_t NumElems) {
return Allocator->Allocate<T>(NumElems);
}
- // Deallocate data that was allocated via allocate<T>().
+ /// Deallocate data that was allocated via allocate<T>().
template <typename T> void deallocate(T *Object) {
Allocator->Deallocate(Object);
}
- // Deallocate data that was allocated via allocateArrayOf<T>().
+ /// Deallocate data that was allocated via allocateArrayOf<T>().
template <typename T> void deallocateArrayOf(T *Array) {
Allocator->Deallocate(Array);
}
@@ -197,17 +220,17 @@
private:
Cfg(GlobalContext *Ctx, uint32_t SequenceNumber);
- // Adds a call to the ProfileSummary runtime function as the first instruction
- // in this CFG's entry block.
+ /// Adds a call to the ProfileSummary runtime function as the first
+ /// instruction in this CFG's entry block.
void addCallToProfileSummary();
- // Iterates over the basic blocks in this CFG, adding profiling code to each
- // one of them. It returns a list with all the globals that the profiling code
- // needs to be defined.
+ /// Iterates over the basic blocks in this CFG, adding profiling code to each
+ /// one of them. It returns a list with all the globals that the profiling
+ /// code needs to be defined.
void profileBlocks();
GlobalContext *Ctx;
- uint32_t SequenceNumber; // output order for emission
+ uint32_t SequenceNumber; /// output order for emission
VerboseMask VMask;
IceString FunctionName = "";
Type ReturnType = IceType_void;
@@ -215,31 +238,31 @@
bool HasError = false;
bool FocusedTiming = false;
IceString ErrorMessage = "";
- CfgNode *Entry = nullptr; // entry basic block
- NodeList Nodes; // linearized node list; Entry should be first
+ CfgNode *Entry = nullptr; /// entry basic block
+ NodeList Nodes; /// linearized node list; Entry should be first
std::vector<IceString> IdentifierNames;
InstNumberT NextInstNumber;
VarList Variables;
- VarList Args; // subset of Variables, in argument order
- VarList ImplicitArgs; // subset of Variables
+ VarList Args; /// subset of Variables, in argument order
+ VarList ImplicitArgs; /// subset of Variables
std::unique_ptr<ArenaAllocator<>> Allocator;
std::unique_ptr<Liveness> Live;
std::unique_ptr<TargetLowering> Target;
std::unique_ptr<VariablesMetadata> VMetadata;
std::unique_ptr<Assembler> TargetAssembler;
- // Globals required by this CFG. Mostly used for the profiler's globals.
+ /// Globals required by this CFG. Mostly used for the profiler's globals.
std::unique_ptr<VariableDeclarationList> GlobalInits;
- // CurrentNode is maintained during dumping/emitting just for
- // validating Variable::DefNode. Normally, a traversal over
- // CfgNodes maintains this, but before global operations like
- // register allocation, resetCurrentNode() should be called to avoid
- // spurious validation failures.
+ /// CurrentNode is maintained during dumping/emitting just for
+ /// validating Variable::DefNode. Normally, a traversal over
+ /// CfgNodes maintains this, but before global operations like
+ /// register allocation, resetCurrentNode() should be called to avoid
+ /// spurious validation failures.
const CfgNode *CurrentNode = nullptr;
- // Maintain a pointer in TLS to the current Cfg being translated.
- // This is primarily for accessing its allocator statelessly, but
- // other uses are possible.
+ /// Maintain a pointer in TLS to the current Cfg being translated.
+ /// This is primarily for accessing its allocator statelessly, but
+ /// other uses are possible.
ICE_TLS_DECLARE_FIELD(const Cfg *, CurrentCfg);
public:
diff --git a/src/IceCfgNode.cpp b/src/IceCfgNode.cpp
index 5ff6936..3f8b39b 100644
--- a/src/IceCfgNode.cpp
+++ b/src/IceCfgNode.cpp
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the CfgNode class, including the complexities
-// of instruction insertion and in-edge calculation.
-//
+///
+/// \file
+/// This file implements the CfgNode class, including the complexities
+/// of instruction insertion and in-edge calculation.
+///
//===----------------------------------------------------------------------===//
#include "IceCfgNode.h"
diff --git a/src/IceCfgNode.h b/src/IceCfgNode.h
index 3afc446..4f3d7d0 100644
--- a/src/IceCfgNode.h
+++ b/src/IceCfgNode.h
@@ -6,11 +6,12 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the CfgNode class, which represents a single
-// basic block as its instruction list, in-edge list, and out-edge
-// list.
-//
+///
+/// \file
+/// This file declares the CfgNode class, which represents a single
+/// basic block as its instruction list, in-edge list, and out-edge
+/// list.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICECFGNODE_H
@@ -31,7 +32,7 @@
return new (Func->allocate<CfgNode>()) CfgNode(Func, LabelIndex);
}
- // Access the label number and name for this node.
+ /// Access the label number and name for this node.
SizeT getIndex() const { return Number; }
void resetIndex(SizeT NewNumber) { Number = NewNumber; }
IceString getName() const;
@@ -45,34 +46,42 @@
return ".L" + Func->getFunctionName() + "$" + getName();
}
- // The HasReturn flag indicates that this node contains a return
- // instruction and therefore needs an epilog.
+ /// The HasReturn flag indicates that this node contains a return
+ /// instruction and therefore needs an epilog.
void setHasReturn() { HasReturn = true; }
bool getHasReturn() const { return HasReturn; }
void setNeedsPlacement(bool Value) { NeedsPlacement = Value; }
bool needsPlacement() const { return NeedsPlacement; }
- // Access predecessor and successor edge lists.
+ /// \name Access predecessor and successor edge lists.
+ /// @{
const NodeList &getInEdges() const { return InEdges; }
const NodeList &getOutEdges() const { return OutEdges; }
+ /// @}
- // Manage the instruction list.
+ /// \name Manage the instruction list.
+ /// @{
InstList &getInsts() { return Insts; }
PhiList &getPhis() { return Phis; }
void appendInst(Inst *Inst);
void renumberInstructions();
- // Rough and generally conservative estimate of the number of
- // instructions in the block. It is updated when an instruction is
- // added, but not when deleted. It is recomputed during
- // renumberInstructions().
+ /// Rough and generally conservative estimate of the number of
+ /// instructions in the block. It is updated when an instruction is
+ /// added, but not when deleted. It is recomputed during
+ /// renumberInstructions().
InstNumberT getInstCountEstimate() const { return InstCountEstimate; }
+ /// @}
- // Add a predecessor edge to the InEdges list for each of this
- // node's successors.
+ /// \name Manage predecessors and successors.
+ /// @{
+
+ /// Add a predecessor edge to the InEdges list for each of this
+ /// node's successors.
void computePredecessors();
void computeSuccessors();
CfgNode *splitIncomingEdge(CfgNode *Pred, SizeT InEdgeIndex);
+ /// @}
void placePhiLoads();
void placePhiStores();
@@ -96,16 +105,16 @@
private:
CfgNode(Cfg *Func, SizeT LabelIndex);
Cfg *const Func;
- SizeT Number; // label index
+ SizeT Number; /// label index
Cfg::IdentifierIndexType NameIndex =
- Cfg::IdentifierIndexInvalid; // index into Cfg::NodeNames table
- bool HasReturn = false; // does this block need an epilog?
+ Cfg::IdentifierIndexInvalid; /// index into Cfg::NodeNames table
+ bool HasReturn = false; /// does this block need an epilog?
bool NeedsPlacement = false;
- InstNumberT InstCountEstimate = 0; // rough instruction count estimate
- NodeList InEdges; // in no particular order
- NodeList OutEdges; // in no particular order
- PhiList Phis; // unordered set of phi instructions
- InstList Insts; // ordered list of non-phi instructions
+ InstNumberT InstCountEstimate = 0; /// rough instruction count estimate
+ NodeList InEdges; /// in no particular order
+ NodeList OutEdges; /// in no particular order
+ PhiList Phis; /// unordered set of phi instructions
+ InstList Insts; /// ordered list of non-phi instructions
};
} // end of namespace Ice
diff --git a/src/IceClFlags.cpp b/src/IceClFlags.cpp
index b5893c1..f1aebd2 100644
--- a/src/IceClFlags.cpp
+++ b/src/IceClFlags.cpp
@@ -6,11 +6,12 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines commandline flags parsing.
-// This currently relies on llvm::cl to parse. In the future, the minimal
-// build can have a simpler parser.
-//
+///
+/// \file
+/// This file defines commandline flags parsing.
+/// This currently relies on llvm::cl to parse. In the future, the minimal
+/// build can have a simpler parser.
+///
//===----------------------------------------------------------------------===//
#include "IceClFlags.h"
diff --git a/src/IceClFlags.h b/src/IceClFlags.h
index 2e2cea1..549bf16 100644
--- a/src/IceClFlags.h
+++ b/src/IceClFlags.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares command line flags controlling translation.
-//
+///
+/// \file
+/// This file declares command line flags controlling translation.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICECLFLAGS_H
diff --git a/src/IceClFlagsExtra.h b/src/IceClFlagsExtra.h
index 8d5b118..b105138 100644
--- a/src/IceClFlagsExtra.h
+++ b/src/IceClFlagsExtra.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares command line flags primarily used for non-minimal builds.
-//
+///
+/// \file
+/// This file declares command line flags primarily used for non-minimal builds.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICECLFLAGSEXTRA_H
diff --git a/src/IceCompileServer.cpp b/src/IceCompileServer.cpp
index d36cdfd..23874f0 100644
--- a/src/IceCompileServer.cpp
+++ b/src/IceCompileServer.cpp
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the basic commandline-based compile server.
-//
+///
+/// \file
+/// This file defines the basic commandline-based compile server.
+///
//===----------------------------------------------------------------------===//
#include "IceCompileServer.h"
diff --git a/src/IceCompileServer.h b/src/IceCompileServer.h
index b5093df..e027cbb 100644
--- a/src/IceCompileServer.h
+++ b/src/IceCompileServer.h
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the compile server. Given a compiler implementation,
-// it dispatches compile requests to the implementation.
-//
+///
+/// \file
+/// This file declares the compile server. Given a compiler implementation,
+/// it dispatches compile requests to the implementation.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICECOMPILESERVER_H
@@ -26,17 +27,17 @@
namespace Ice {
-// A CompileServer awaits compile requests, and dispatches the requests
-// to a given Compiler. Each request is paired with an input stream,
-// a context (which has the output stream), and a set of arguments.
-// The CompileServer takes over the current thread to listen to requests,
-// and compile requests are handled on separate threads.
-//
-// Currently, this only handles a single request.
-//
-// When run on the commandline, it receives and therefore dispatches
-// the request immediately. When run in the browser, it blocks waiting
-// for a request.
+/// A CompileServer awaits compile requests, and dispatches the requests
+/// to a given Compiler. Each request is paired with an input stream,
+/// a context (which has the output stream), and a set of arguments.
+/// The CompileServer takes over the current thread to listen to requests,
+/// and compile requests are handled on separate threads.
+///
+/// Currently, this only handles a single request.
+///
+/// When run on the commandline, it receives and therefore dispatches
+/// the request immediately. When run in the browser, it blocks waiting
+/// for a request.
class CompileServer {
CompileServer() = delete;
CompileServer(const CompileServer &) = delete;
@@ -59,7 +60,7 @@
ErrorCode LastError;
};
-// Commandline variant of the compile server.
+/// Commandline variant of the compile server.
class CLCompileServer : public CompileServer {
CLCompileServer() = delete;
CLCompileServer(const CLCompileServer &) = delete;
diff --git a/src/IceCompiler.cpp b/src/IceCompiler.cpp
index 7764b71..59f18d2 100644
--- a/src/IceCompiler.cpp
+++ b/src/IceCompiler.cpp
@@ -6,13 +6,14 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines a driver for translating PNaCl bitcode into native code.
-// It can either directly parse the binary bitcode file, or use LLVM routines to
-// parse a textual bitcode file into LLVM IR and then convert LLVM IR into ICE.
-// In either case, the high-level ICE is then compiled down to native code, as
-// either an ELF object file or a textual asm file.
-//
+///
+/// \file
+/// This file defines a driver for translating PNaCl bitcode into native code.
+/// It can either directly parse the binary bitcode file, or use LLVM routines
+/// to parse a textual bitcode file into LLVM IR and then convert LLVM IR into
+/// ICE. In either case, the high-level ICE is then compiled down to native
+/// code, as either an ELF object file or a textual asm file.
+///
//===----------------------------------------------------------------------===//
#include "IceCompiler.h"
diff --git a/src/IceCompiler.h b/src/IceCompiler.h
index 460c327..e121dbb 100644
--- a/src/IceCompiler.h
+++ b/src/IceCompiler.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the driver for translating bitcode to native code.
-//
+///
+/// \file
+/// This file declares the driver for translating bitcode to native code.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICECOMPILER_H
@@ -24,7 +25,7 @@
class ClFlagsExtra;
-// A compiler driver. It may be called to handle a single compile request.
+/// A compiler driver. It may be called to handle a single compile request.
class Compiler {
Compiler(const Compiler &) = delete;
Compiler &operator=(const Compiler &) = delete;
@@ -32,8 +33,8 @@
public:
Compiler() = default;
- // Run the compiler with the given GlobalContext for compilation
- // state. Upon error, the Context's error status will be set.
+ /// Run the compiler with the given GlobalContext for compilation
+ /// state. Upon error, the Context's error status will be set.
void run(const ClFlagsExtra &ExtraFlags, GlobalContext &Ctx,
std::unique_ptr<llvm::DataStreamer> &&InputStream);
};
diff --git a/src/IceConditionCodesARM32.h b/src/IceConditionCodesARM32.h
index b98c770..d897a44 100644
--- a/src/IceConditionCodesARM32.h
+++ b/src/IceConditionCodesARM32.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the condition codes for ARM32.
-//
+///
+/// \file
+/// This file declares the condition codes for ARM32.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICECONDITIONCODESARM32_H
@@ -25,8 +26,8 @@
CondARM32 &operator=(const CondARM32 &) = delete;
public:
- // An enum of codes used for conditional instructions. The enum value
- // should match the value used to encode operands in binary instructions.
+ /// An enum of codes used for conditional instructions. The enum value
+ /// should match the value used to encode operands in binary instructions.
enum Cond {
#define X(tag, encode, opp, emit) tag = encode,
ICEINSTARM32COND_TABLE
diff --git a/src/IceConditionCodesX8632.h b/src/IceConditionCodesX8632.h
index 77dd4c7..eb09687 100644
--- a/src/IceConditionCodesX8632.h
+++ b/src/IceConditionCodesX8632.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the condition codes for x86-32.
-//
+///
+/// \file
+/// This file declares the condition codes for x86-32.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICECONDITIONCODESX8632_H
@@ -25,8 +26,8 @@
CondX86 &operator=(const CondX86 &) = delete;
public:
- // An enum of condition codes used for branches and cmov. The enum value
- // should match the value used to encode operands in binary instructions.
+ /// An enum of condition codes used for branches and cmov. The enum value
+ /// should match the value used to encode operands in binary instructions.
enum BrCond {
#define X(tag, encode, opp, dump, emit) tag encode,
ICEINSTX8632BR_TABLE
@@ -34,9 +35,9 @@
Br_None
};
- // An enum of condition codes relevant to the CMPPS instruction. The enum
- // value should match the value used to encode operands in binary
- // instructions.
+ /// An enum of condition codes relevant to the CMPPS instruction. The enum
+ /// value should match the value used to encode operands in binary
+ /// instructions.
enum CmppsCond {
#define X(tag, emit) tag,
ICEINSTX8632CMPPS_TABLE
diff --git a/src/IceConditionCodesX8664.h b/src/IceConditionCodesX8664.h
index ec30f88..06155ea 100644
--- a/src/IceConditionCodesX8664.h
+++ b/src/IceConditionCodesX8664.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the condition codes for x86-64.
-//
+///
+/// \file
+/// This file declares the condition codes for x86-64.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICECONDITIONCODESX8664_H
@@ -20,8 +21,8 @@
namespace Ice {
class CondX8664 {
- // An enum of condition codes used for branches and cmov. The enum value
- // should match the value used to encode operands in binary instructions.
+ /// An enum of condition codes used for branches and cmov. The enum value
+ /// should match the value used to encode operands in binary instructions.
enum BrCond {
#define X(tag, encode, opp, dump, emit) tag encode,
ICEINSTX8664BR_TABLE
@@ -29,9 +30,9 @@
Br_None
};
- // An enum of condition codes relevant to the CMPPS instruction. The enum
- // value should match the value used to encode operands in binary
- // instructions.
+ /// An enum of condition codes relevant to the CMPPS instruction. The enum
+ /// value should match the value used to encode operands in binary
+ /// instructions.
enum CmppsCond {
#define X(tag, emit) tag,
ICEINSTX8664CMPPS_TABLE
diff --git a/src/IceConverter.cpp b/src/IceConverter.cpp
index d389a02..0fe6f10 100644
--- a/src/IceConverter.cpp
+++ b/src/IceConverter.cpp
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the LLVM to ICE converter.
-//
+///
+/// \file
+/// This file implements the LLVM to ICE converter.
+///
//===----------------------------------------------------------------------===//
#include "IceConverter.h"
diff --git a/src/IceConverter.h b/src/IceConverter.h
index 84389d3..f2dbb3a 100644
--- a/src/IceConverter.h
+++ b/src/IceConverter.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the LLVM to ICE converter.
-//
+///
+/// \file
+/// This file declares the LLVM to ICE converter.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICECONVERTER_H
@@ -41,8 +42,8 @@
llvm::Module *getModule() const { return Mod; }
- // Returns the global declaration associated with the corresponding
- // global value V. If no such global address, generates fatal error.
+ /// Returns the global declaration associated with the corresponding
+ /// global value V. If no such global address, generates fatal error.
GlobalDeclaration *getGlobalDeclaration(const llvm::GlobalValue *V);
private:
@@ -51,22 +52,22 @@
GlobalDeclarationMapType;
GlobalDeclarationMapType GlobalDeclarationMap;
- // Walks module and generates names for unnamed globals using prefix
- // getFlags().DefaultGlobalPrefix, if the prefix is non-empty.
+ /// Walks module and generates names for unnamed globals using prefix
+ /// getFlags().DefaultGlobalPrefix, if the prefix is non-empty.
void nameUnnamedGlobalVariables(llvm::Module *Mod);
- // Walks module and generates names for unnamed functions using
- // prefix getFlags().DefaultFunctionPrefix, if the prefix is
- // non-empty.
+ /// Walks module and generates names for unnamed functions using
+ /// prefix getFlags().DefaultFunctionPrefix, if the prefix is
+ /// non-empty.
void nameUnnamedFunctions(llvm::Module *Mod);
- // Converts functions to ICE, and then machine code.
+ /// Converts functions to ICE, and then machine code.
void convertFunctions();
- // Converts globals to ICE, and then machine code.
+ /// Converts globals to ICE, and then machine code.
void convertGlobals(llvm::Module *Mod);
- // Installs global declarations into GlobalDeclarationMap.
+ /// Installs global declarations into GlobalDeclarationMap.
void installGlobalDeclarations(llvm::Module *Mod);
};
diff --git a/src/IceDefs.h b/src/IceDefs.h
index 2ee41a7..17e2fb1 100644
--- a/src/IceDefs.h
+++ b/src/IceDefs.h
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares various useful types and classes that have widespread use
-// across Subzero. Every Subzero source file is expected to include IceDefs.h.
-//
+///
+/// \file
+/// This file declares various useful types and classes that have widespread use
+/// across Subzero. Every Subzero source file is expected to include IceDefs.h.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEDEFS_H
@@ -147,18 +148,18 @@
typedef std::vector<VariableDeclaration *> VariableDeclarationList;
-// SizeT is for holding small-ish limits like number of source
-// operands in an instruction. It is used instead of size_t (which
-// may be 64-bits wide) when we want to save space.
+/// SizeT is for holding small-ish limits like number of source
+/// operands in an instruction. It is used instead of size_t (which
+/// may be 64-bits wide) when we want to save space.
typedef uint32_t SizeT;
-// InstNumberT is for holding an instruction number. Instruction
-// numbers are used for representing Variable live ranges.
+/// InstNumberT is for holding an instruction number. Instruction
+/// numbers are used for representing Variable live ranges.
typedef int32_t InstNumberT;
-// A LiveBeginEndMapEntry maps a Variable::Number value to an
-// Inst::Number value, giving the instruction number that begins or
-// ends a variable's live range.
+/// A LiveBeginEndMapEntry maps a Variable::Number value to an
+/// Inst::Number value, giving the instruction number that begins or
+/// ends a variable's live range.
typedef std::pair<SizeT, InstNumberT> LiveBeginEndMapEntry;
typedef std::vector<LiveBeginEndMapEntry,
CfgLocalAllocator<LiveBeginEndMapEntry>> LiveBeginEndMap;
@@ -167,9 +168,9 @@
typedef uint32_t TimerStackIdT;
typedef uint32_t TimerIdT;
-// Use alignas(MaxCacheLineSize) to isolate variables/fields that
-// might be contended while multithreading. Assumes the maximum cache
-// line size is 64.
+/// Use alignas(MaxCacheLineSize) to isolate variables/fields that
+/// might be contended while multithreading. Assumes the maximum cache
+/// line size is 64.
enum { MaxCacheLineSize = 64 };
// Use ICE_CACHELINE_BOUNDARY to force the next field in a declaration
// list to be aligned to the next cache line.
@@ -178,26 +179,26 @@
#define ICE_CACHELINE_BOUNDARY \
__attribute__((aligned(MaxCacheLineSize + 0))) int : 0
-// PNaCl is ILP32, so theoretically we should only need 32-bit offsets.
+/// PNaCl is ILP32, so theoretically we should only need 32-bit offsets.
typedef int32_t RelocOffsetT;
enum { RelocAddrSize = 4 };
enum LivenessMode {
- // Basic version of live-range-end calculation. Marks the last uses
- // of variables based on dataflow analysis. Records the set of
- // live-in and live-out variables for each block. Identifies and
- // deletes dead instructions (primarily stores).
+ /// Basic version of live-range-end calculation. Marks the last uses
+ /// of variables based on dataflow analysis. Records the set of
+ /// live-in and live-out variables for each block. Identifies and
+ /// deletes dead instructions (primarily stores).
Liveness_Basic,
- // In addition to Liveness_Basic, also calculate the complete
- // live range for each variable in a form suitable for interference
- // calculation and register allocation.
+ /// In addition to Liveness_Basic, also calculate the complete
+ /// live range for each variable in a form suitable for interference
+ /// calculation and register allocation.
Liveness_Intervals
};
enum RegAllocKind {
- RAK_Global, // full, global register allocation
- RAK_InfOnly // allocation only for infinite-weight Variables
+ RAK_Global, /// full, global register allocation
+ RAK_InfOnly /// allocation only for infinite-weight Variables
};
enum VerboseItem {
@@ -221,9 +222,9 @@
typedef uint32_t VerboseMask;
enum FileType {
- FT_Elf, // ELF .o file
- FT_Asm, // Assembly .s file
- FT_Iasm // "Integrated assembler" .byte-style .s file
+ FT_Elf, /// ELF .o file
+ FT_Asm, /// Assembly .s file
+ FT_Iasm /// "Integrated assembler" .byte-style .s file
};
typedef llvm::raw_ostream Ostream;
@@ -233,10 +234,10 @@
enum ErrorCodes { EC_None = 0, EC_Args, EC_Bitcode, EC_Translation };
-// Wrapper around std::error_code for allowing multiple errors to be
-// folded into one. The current implementation keeps track of the
-// first error, which is likely to be the most useful one, and this
-// could be extended to e.g. collect a vector of errors.
+/// Wrapper around std::error_code for allowing multiple errors to be
+/// folded into one. The current implementation keeps track of the
+/// first error, which is likely to be the most useful one, and this
+/// could be extended to e.g. collect a vector of errors.
class ErrorCode : public std::error_code {
ErrorCode(const ErrorCode &) = delete;
ErrorCode &operator=(const ErrorCode &) = delete;
@@ -255,7 +256,7 @@
bool HasError = false;
};
-// Reverse range adaptors written in terms of llvm::make_range().
+/// Reverse range adaptors written in terms of llvm::make_range().
template <typename T>
llvm::iterator_range<typename T::const_reverse_iterator>
reverse_range(const T &Container) {
@@ -266,7 +267,7 @@
return llvm::make_range(Container.rbegin(), Container.rend());
}
-// Options for pooling and randomization of immediates
+/// Options for pooling and randomization of immediates.
enum RandomizeAndPoolImmediatesEnum { RPI_None, RPI_Randomize, RPI_Pool };
} // end of namespace Ice
diff --git a/src/IceELFObjectWriter.cpp b/src/IceELFObjectWriter.cpp
index eca3403..37b1d58 100644
--- a/src/IceELFObjectWriter.cpp
+++ b/src/IceELFObjectWriter.cpp
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the writer for ELF relocatable object files.
-//
+///
+/// \file
+/// This file defines the writer for ELF relocatable object files.
+///
//===----------------------------------------------------------------------===//
#include "IceELFObjectWriter.h"
diff --git a/src/IceELFObjectWriter.h b/src/IceELFObjectWriter.h
index 9356ee3..0562c9b 100644
--- a/src/IceELFObjectWriter.h
+++ b/src/IceELFObjectWriter.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// Abstraction for a writer that is responsible for writing an ELF file.
-//
+///
+/// \file
+/// Abstraction for a writer that is responsible for writing an ELF file.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEELFOBJECTWRITER_H
@@ -23,26 +24,26 @@
namespace Ice {
-// Higher level ELF object writer. Manages section information and writes
-// the final ELF object. The object writer will write to file the code
-// and data as it is being defined (rather than keep a copy).
-// After all definitions are written out, it will finalize the bookkeeping
-// sections and write them out. Expected usage:
-//
-// (1) writeInitialELFHeader (invoke once)
-// (2) writeDataSection (may be invoked multiple times, as long as
-// SectionSuffix is unique)
-// (3) writeFunctionCode (must invoke once per function)
-// (4) writeConstantPool (must invoke once per pooled primitive type)
-// (5) setUndefinedSyms (invoke once)
-// (6) writeNonUserSections (invoke once)
-//
-// The requirement for writeDataSection to be invoked only once can
-// be relaxed if using -fdata-sections. The requirement to invoke only once
-// without -fdata-sections is so that variables that belong to each possible
-// SectionType are contiguous in the file. With -fdata-sections, each global
-// variable is in a separate section and therefore the sections will be
-// trivially contiguous.
+/// Higher level ELF object writer. Manages section information and writes
+/// the final ELF object. The object writer will write to file the code
+/// and data as it is being defined (rather than keep a copy).
+/// After all definitions are written out, it will finalize the bookkeeping
+/// sections and write them out. Expected usage:
+///
+/// (1) writeInitialELFHeader (invoke once)
+/// (2) writeDataSection (may be invoked multiple times, as long as
+/// SectionSuffix is unique)
+/// (3) writeFunctionCode (must invoke once per function)
+/// (4) writeConstantPool (must invoke once per pooled primitive type)
+/// (5) setUndefinedSyms (invoke once)
+/// (6) writeNonUserSections (invoke once)
+///
+/// The requirement for writeDataSection to be invoked only once can
+/// be relaxed if using -fdata-sections. The requirement to invoke only once
+/// without -fdata-sections is so that variables that belong to each possible
+/// SectionType are contiguous in the file. With -fdata-sections, each global
+/// variable is in a separate section and therefore the sections will be
+/// trivially contiguous.
class ELFObjectWriter {
ELFObjectWriter() = delete;
ELFObjectWriter(const ELFObjectWriter &) = delete;
@@ -51,39 +52,39 @@
public:
ELFObjectWriter(GlobalContext &Ctx, ELFStreamer &Out);
- // Write the initial ELF header. This is just to reserve space in the ELF
- // file. Reserving space allows the other functions to write text
- // and data directly to the file and get the right file offsets.
+ /// Write the initial ELF header. This is just to reserve space in the ELF
+ /// file. Reserving space allows the other functions to write text
+ /// and data directly to the file and get the right file offsets.
void writeInitialELFHeader();
- // Copy initializer data for globals to file and note the offset and size
- // of each global's definition in the symbol table.
- // Use the given target's RelocationKind for any relocations.
+ /// Copy initializer data for globals to file and note the offset and size
+ /// of each global's definition in the symbol table.
+ /// Use the given target's RelocationKind for any relocations.
void writeDataSection(const VariableDeclarationList &Vars,
FixupKind RelocationKind,
const IceString &SectionSuffix);
- // Copy data of a function's text section to file and note the offset of the
- // symbol's definition in the symbol table.
- // Copy the text fixups for use after all functions are written.
- // The text buffer and fixups are extracted from the Assembler object.
+ /// Copy data of a function's text section to file and note the offset of the
+ /// symbol's definition in the symbol table.
+ /// Copy the text fixups for use after all functions are written.
+ /// The text buffer and fixups are extracted from the Assembler object.
void writeFunctionCode(const IceString &FuncName, bool IsInternal,
const Assembler *Asm);
- // Queries the GlobalContext for constant pools of the given type
- // and writes out read-only data sections for those constants. This also
- // fills the symbol table with labels for each constant pool entry.
+ /// Queries the GlobalContext for constant pools of the given type
+ /// and writes out read-only data sections for those constants. This also
+ /// fills the symbol table with labels for each constant pool entry.
template <typename ConstType> void writeConstantPool(Type Ty);
- // Populate the symbol table with a list of external/undefined symbols.
+ /// Populate the symbol table with a list of external/undefined symbols.
void setUndefinedSyms(const ConstantList &UndefSyms);
- // Do final layout and write out the rest of the object file.
- // Finally, patch up the initial ELF header with the final info.
+ /// Do final layout and write out the rest of the object file.
+ /// Finally, patch up the initial ELF header with the final info.
void writeNonUserSections();
- // Which type of ELF section a global variable initializer belongs to.
- // This is used as an array index so should start at 0 and be contiguous.
+ /// Which type of ELF section a global variable initializer belongs to.
+ /// This is used as an array index so should start at 0 and be contiguous.
enum SectionType { ROData = 0, Data, BSS, NumSectionTypes };
private:
@@ -116,48 +117,48 @@
Elf64_Xword ShFlags, Elf64_Xword ShAddralign,
Elf64_Xword ShEntsize);
- // Create a relocation section, given the related section
- // (e.g., .text, .data., .rodata).
+ /// Create a relocation section, given the related section
+ /// (e.g., .text, .data., .rodata).
ELFRelocationSection *
createRelocationSection(const ELFSection *RelatedSection);
- // Align the file position before writing out a section's data,
- // and return the position of the file.
+ /// Align the file position before writing out a section's data,
+ /// and return the position of the file.
Elf64_Off alignFileOffset(Elf64_Xword Align);
- // Assign an ordering / section numbers to each section.
- // Fill in other information that is only known near the end
- // (such as the size, if it wasn't already incrementally updated).
- // This then collects all sections in the decided order, into one vector,
- // for conveniently writing out all of the section headers.
+ /// Assign an ordering / section numbers to each section.
+ /// Fill in other information that is only known near the end
+ /// (such as the size, if it wasn't already incrementally updated).
+ /// This then collects all sections in the decided order, into one vector,
+ /// for conveniently writing out all of the section headers.
void assignSectionNumbersInfo(SectionList &AllSections);
- // This function assigns .foo and .rel.foo consecutive section numbers.
- // It also sets the relocation section's sh_info field to the related
- // section's number.
+ /// This function assigns .foo and .rel.foo consecutive section numbers.
+ /// It also sets the relocation section's sh_info field to the related
+ /// section's number.
template <typename UserSectionList>
void assignRelSectionNumInPairs(SizeT &CurSectionNumber,
UserSectionList &UserSections,
RelSectionList &RelSections,
SectionList &AllSections);
- // Link the relocation sections to the symbol table.
+ /// Link the relocation sections to the symbol table.
void assignRelLinkNum(SizeT SymTabNumber, RelSectionList &RelSections);
- // Helper function for writeDataSection. Writes a data section of type
- // SectionType, given the global variables Vars belonging to that SectionType.
+ /// Helper function for writeDataSection. Writes a data section of type
+ /// SectionType, given the global variables Vars belonging to that SectionType.
void writeDataOfType(SectionType SectionType,
const VariableDeclarationList &Vars,
FixupKind RelocationKind,
const IceString &SectionSuffix);
- // Write the final relocation sections given the final symbol table.
- // May also be able to seek around the file and resolve function calls
- // that are for functions within the same section.
+ /// Write the final relocation sections given the final symbol table.
+ /// May also be able to seek around the file and resolve function calls
+ /// that are for functions within the same section.
void writeAllRelocationSections();
void writeRelocationSections(RelSectionList &RelSections);
- // Write the ELF file header with the given information about sections.
+ /// Write the ELF file header with the given information about sections.
template <bool IsELF64>
void writeELFHeaderInternal(Elf64_Off SectionHeaderOffset,
SizeT SectHeaderStrIndex, SizeT NumSections);
diff --git a/src/IceELFSection.cpp b/src/IceELFSection.cpp
index 8ca5b2d..7893354 100644
--- a/src/IceELFSection.cpp
+++ b/src/IceELFSection.cpp
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines how ELF sections are represented.
-//
+///
+/// \file
+/// This file defines how ELF sections are represented.
+///
//===----------------------------------------------------------------------===//
#include "IceELFSection.h"
diff --git a/src/IceELFSection.h b/src/IceELFSection.h
index a79a9fb..0ee3f03 100644
--- a/src/IceELFSection.h
+++ b/src/IceELFSection.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// Representation of ELF sections.
-//
+///
+/// \file
+/// Representation of ELF sections.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEELFSECTION_H
@@ -26,7 +27,7 @@
class ELFStreamer;
class ELFStringTableSection;
-// Base representation of an ELF section.
+/// Base representation of an ELF section.
class ELFSection {
ELFSection() = delete;
ELFSection(const ELFSection &) = delete;
@@ -35,15 +36,15 @@
public:
virtual ~ELFSection() = default;
- // Sentinel value for a section number/index for before the final
- // section index is actually known. The dummy NULL section will be assigned
- // number 0, and it is referenced by the dummy 0-th symbol in the symbol
- // table, so use max() instead of 0.
+ /// Sentinel value for a section number/index for before the final
+ /// section index is actually known. The dummy NULL section will be assigned
+ /// number 0, and it is referenced by the dummy 0-th symbol in the symbol
+ /// table, so use max() instead of 0.
enum { NoSectionNumber = std::numeric_limits<SizeT>::max() };
- // Constructs an ELF section, filling in fields that will be known
- // once the *type* of section is decided. Other fields may be updated
- // incrementally or only after the program is completely defined.
+ /// Constructs an ELF section, filling in fields that will be known
+ /// once the *type* of section is decided. Other fields may be updated
+ /// incrementally or only after the program is completely defined.
ELFSection(const IceString &Name, Elf64_Word ShType, Elf64_Xword ShFlags,
Elf64_Xword ShAddralign, Elf64_Xword ShEntsize)
: Name(Name), Header() {
@@ -53,7 +54,7 @@
Header.sh_entsize = ShEntsize;
}
- // Set the section number/index after it is finally known.
+ /// Set the section number/index after it is finally known.
void setNumber(SizeT N) {
// Should only set the number once: from NoSectionNumber -> N.
assert(Number == NoSectionNumber);
@@ -79,24 +80,24 @@
Elf64_Xword getSectionAlign() const { return Header.sh_addralign; }
- // Write the section header out with the given streamer.
+ /// Write the section header out with the given streamer.
template <bool IsELF64> void writeHeader(ELFStreamer &Str);
protected:
- // Name of the section in convenient string form (instead of a index
- // into the Section Header String Table, which is not known till later).
+ /// Name of the section in convenient string form (instead of a index
+ /// into the Section Header String Table, which is not known till later).
const IceString Name;
// The fields of the header. May only be partially initialized, but should
// be fully initialized before writing.
Elf64_Shdr Header;
- // The number of the section after laying out sections.
+ /// The number of the section after laying out sections.
SizeT Number = NoSectionNumber;
};
-// Models text/code sections. Code is written out incrementally and the
-// size of the section is then updated incrementally.
+/// Models text/code sections. Code is written out incrementally and the
+/// size of the section is then updated incrementally.
class ELFTextSection : public ELFSection {
ELFTextSection() = delete;
ELFTextSection(const ELFTextSection &) = delete;
@@ -108,9 +109,9 @@
void appendData(ELFStreamer &Str, const llvm::StringRef MoreData);
};
-// Models data/rodata sections. Data is written out incrementally and the
-// size of the section is then updated incrementally.
-// Some rodata sections may have fixed entsize and duplicates may be mergeable.
+/// Models data/rodata sections. Data is written out incrementally and the
+/// size of the section is then updated incrementally.
+/// Some rodata sections may have fixed entsize and duplicates may be mergeable.
class ELFDataSection : public ELFSection {
ELFDataSection() = delete;
ELFDataSection(const ELFDataSection &) = delete;
@@ -126,22 +127,22 @@
void appendRelocationOffset(ELFStreamer &Str, bool IsRela,
RelocOffsetT RelocOffset);
- // Pad the next section offset for writing data elements to the requested
- // alignment. If the section is NOBITS then do not actually write out
- // the padding and only update the section size.
+ /// Pad the next section offset for writing data elements to the requested
+ /// alignment. If the section is NOBITS then do not actually write out
+ /// the padding and only update the section size.
void padToAlignment(ELFStreamer &Str, Elf64_Xword Align);
};
-// Model of ELF symbol table entries. Besides keeping track of the fields
-// required for an elf symbol table entry it also tracks the number that
-// represents the symbol's final index in the symbol table.
+/// Model of ELF symbol table entries. Besides keeping track of the fields
+/// required for an elf symbol table entry it also tracks the number that
+/// represents the symbol's final index in the symbol table.
struct ELFSym {
Elf64_Sym Sym;
ELFSection *Section;
SizeT Number;
- // Sentinel value for symbols that haven't been assigned a number yet.
- // The dummy 0-th symbol will be assigned number 0, so don't use that.
+ /// Sentinel value for symbols that haven't been assigned a number yet.
+ /// The dummy 0-th symbol will be assigned number 0, so don't use that.
enum { UnknownNumber = std::numeric_limits<SizeT>::max() };
void setNumber(SizeT N) {
@@ -155,8 +156,8 @@
}
};
-// Models a symbol table. Symbols may be added up until updateIndices is
-// called. At that point the indices of each symbol will be finalized.
+/// Models a symbol table. Symbols may be added up until updateIndices is
+/// called. At that point the indices of each symbol will be finalized.
class ELFSymbolTableSection : public ELFSection {
ELFSymbolTableSection() = delete;
ELFSymbolTableSection(const ELFSymbolTableSection &) = delete;
@@ -169,16 +170,16 @@
: ELFSection(Name, ShType, ShFlags, ShAddralign, ShEntsize),
NullSymbol(nullptr) {}
- // Create initial entry for a symbol when it is defined.
- // Each entry should only be defined once.
- // We might want to allow Name to be a dummy name initially, then
- // get updated to the real thing, since Data initializers are read
- // before the bitcode's symbol table is read.
+ /// Create initial entry for a symbol when it is defined.
+ /// Each entry should only be defined once.
+ /// We might want to allow Name to be a dummy name initially, then
+ /// get updated to the real thing, since Data initializers are read
+ /// before the bitcode's symbol table is read.
void createDefinedSym(const IceString &Name, uint8_t Type, uint8_t Binding,
ELFSection *Section, RelocOffsetT Offset, SizeT Size);
- // Note that a symbol table entry needs to be created for the given
- // symbol because it is undefined.
+ /// Note that a symbol table entry needs to be created for the given
+ /// symbol because it is undefined.
void noteUndefinedSym(const IceString &Name, ELFSection *NullSection);
const ELFSym *findSymbol(const IceString &Name) const;
@@ -212,7 +213,7 @@
SymMap GlobalSymbols;
};
-// Models a relocation section.
+/// Models a relocation section.
class ELFRelocationSection : public ELFSection {
ELFRelocationSection() = delete;
ELFRelocationSection(const ELFRelocationSection &) = delete;
@@ -230,11 +231,11 @@
RelatedSection = Section;
}
- // Track additional relocations which start out relative to offset 0,
- // but should be adjusted to be relative to BaseOff.
+ /// Track additional relocations which start out relative to offset 0,
+ /// but should be adjusted to be relative to BaseOff.
void addRelocations(RelocOffsetT BaseOff, const FixupRefList &FixupRefs);
- // Track a single additional relocation.
+ /// Track a single additional relocation.
void addRelocation(const AssemblerFixup &Fixup) { Fixups.push_back(Fixup); }
size_t getSectionDataSize() const;
@@ -250,12 +251,12 @@
FixupList Fixups;
};
-// Models a string table. The user will build the string table by
-// adding strings incrementally. At some point, all strings should be
-// known and doLayout() should be called. After that, no other
-// strings may be added. However, the final offsets of the strings
-// can be discovered and used to fill out section headers and symbol
-// table entries.
+/// Models a string table. The user will build the string table by
+/// adding strings incrementally. At some point, all strings should be
+/// known and doLayout() should be called. After that, no other
+/// strings may be added. However, the final offsets of the strings
+/// can be discovered and used to fill out section headers and symbol
+/// table entries.
class ELFStringTableSection : public ELFSection {
ELFStringTableSection() = delete;
ELFStringTableSection(const ELFStringTableSection &) = delete;
@@ -264,18 +265,18 @@
public:
using ELFSection::ELFSection;
- // Add a string to the table, in preparation for final layout.
+ /// Add a string to the table, in preparation for final layout.
void add(const IceString &Str);
- // Finalizes the layout of the string table and fills in the section Data.
+ /// Finalizes the layout of the string table and fills in the section Data.
void doLayout();
- // The first byte of the string table should be \0, so it is an
- // invalid index. Indices start out as unknown until layout is complete.
+ /// The first byte of the string table should be \0, so it is an
+ /// invalid index. Indices start out as unknown until layout is complete.
enum { UnknownIndex = 0 };
- // Grabs the final index of a string after layout. Returns UnknownIndex
- // if the string's index is not found.
+ /// Grabs the final index of a string after layout. Returns UnknownIndex
+ /// if the string's index is not found.
size_t getIndex(const IceString &Str) const;
llvm::StringRef getSectionData() const {
@@ -289,19 +290,19 @@
private:
bool isLaidOut() const { return !StringData.empty(); }
- // Strings can share a string table entry if they share the same
- // suffix. E.g., "pop" and "lollipop" can both use the characters
- // in "lollipop", but "pops" cannot, and "unpop" cannot either.
- // Though, "pop", "lollipop", and "unpop" share "pop" as the suffix,
- // "pop" can only share the characters with one of them.
+ /// Strings can share a string table entry if they share the same
+ /// suffix. E.g., "pop" and "lollipop" can both use the characters
+ /// in "lollipop", but "pops" cannot, and "unpop" cannot either.
+ /// Though, "pop", "lollipop", and "unpop" share "pop" as the suffix,
+ /// "pop" can only share the characters with one of them.
struct SuffixComparator {
bool operator()(const IceString &StrA, const IceString &StrB) const;
};
typedef std::map<IceString, size_t, SuffixComparator> StringToIndexType;
- // Track strings to their index. Index will be UnknownIndex if not
- // yet laid out.
+ /// Track strings to their index. Index will be UnknownIndex if not
+ /// yet laid out.
StringToIndexType StringToIndexMap;
typedef std::vector<uint8_t> RawDataType;
diff --git a/src/IceELFStreamer.h b/src/IceELFStreamer.h
index 50e4dd7..93051b9 100644
--- a/src/IceELFStreamer.h
+++ b/src/IceELFStreamer.h
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// Interface for serializing bits for common ELF types (words, extended words,
-// etc.), based on the ELF Class.
-//
+///
+/// \file
+/// Interface for serializing bits for common ELF types (words, extended words,
+/// etc.), based on the ELF Class.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEELFSTREAMER_H
@@ -19,8 +20,8 @@
namespace Ice {
-// Low level writer that can that can handle ELFCLASS32/64.
-// Little endian only for now.
+/// Low level writer that can that can handle ELFCLASS32/64.
+/// Little endian only for now.
class ELFStreamer {
ELFStreamer() = delete;
ELFStreamer(const ELFStreamer &) = delete;
diff --git a/src/IceFixups.cpp b/src/IceFixups.cpp
index 9301910..de00d23 100644
--- a/src/IceFixups.cpp
+++ b/src/IceFixups.cpp
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the AssemblerFixup class, a very basic
-// target-independent representation of a fixup or relocation.
-//
+///
+/// \file
+/// This file implements the AssemblerFixup class, a very basic
+/// target-independent representation of a fixup or relocation.
+///
//===----------------------------------------------------------------------===//
#include "IceFixups.h"
diff --git a/src/IceFixups.h b/src/IceFixups.h
index 9ec72c3..f040918 100644
--- a/src/IceFixups.h
+++ b/src/IceFixups.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares generic fixup types.
-//
+///
+/// \file
+/// This file declares generic fixup types.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEFIXUPS_H
@@ -18,12 +19,12 @@
namespace Ice {
-// Each target and container format has a different namespace of relocations.
-// This holds the specific target+container format's relocation number.
+/// Each target and container format has a different namespace of relocations.
+/// This holds the specific target+container format's relocation number.
typedef uint32_t FixupKind;
-// Assembler fixups are positions in generated code/data that hold relocation
-// information that needs to be processed before finalizing the code/data.
+/// Assembler fixups are positions in generated code/data that hold relocation
+/// information that needs to be processed before finalizing the code/data.
struct AssemblerFixup {
AssemblerFixup &operator=(const AssemblerFixup &) = delete;
diff --git a/src/IceGlobalContext.cpp b/src/IceGlobalContext.cpp
index 3473b8c..51ca3f0 100644
--- a/src/IceGlobalContext.cpp
+++ b/src/IceGlobalContext.cpp
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines aspects of the compilation that persist across
-// multiple functions.
-//
+///
+/// \file
+/// This file defines aspects of the compilation that persist across
+/// multiple functions.
+///
//===----------------------------------------------------------------------===//
#include "IceGlobalContext.h"
diff --git a/src/IceGlobalContext.h b/src/IceGlobalContext.h
index 1e23a36..d19249d 100644
--- a/src/IceGlobalContext.h
+++ b/src/IceGlobalContext.h
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares aspects of the compilation that persist across
-// multiple functions.
-//
+///
+/// \file
+/// This file declares aspects of the compilation that persist across
+/// multiple functions.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEGLOBALCONTEXT_H
@@ -38,7 +39,7 @@
class EmitterWorkItem;
class FuncSigType;
-// LockedPtr is a way to provide automatically locked access to some object.
+/// LockedPtr is a way to provide automatically locked access to some object.
template <typename T> class LockedPtr {
LockedPtr() = delete;
LockedPtr(const LockedPtr &) = delete;
@@ -65,7 +66,7 @@
GlobalContext(const GlobalContext &) = delete;
GlobalContext &operator=(const GlobalContext &) = delete;
- // CodeStats collects rudimentary statistics during translation.
+ /// CodeStats collects rudimentary statistics during translation.
class CodeStats {
CodeStats(const CodeStats &) = delete;
CodeStats &operator=(const CodeStats &) = default;
@@ -102,18 +103,18 @@
std::array<uint32_t, CS_NUM> Stats;
};
- // TimerList is a vector of TimerStack objects, with extra methods
- // to initialize and merge these vectors.
+ /// TimerList is a vector of TimerStack objects, with extra methods
+ /// to initialize and merge these vectors.
class TimerList : public std::vector<TimerStack> {
TimerList(const TimerList &) = delete;
TimerList &operator=(const TimerList &) = delete;
public:
TimerList() = default;
- // initInto() initializes a target list of timers based on the
- // current list. In particular, it creates the same number of
- // timers, in the same order, with the same names, but initially
- // empty of timing data.
+ /// initInto() initializes a target list of timers based on the
+ /// current list. In particular, it creates the same number of
+ /// timers, in the same order, with the same names, but initially
+ /// empty of timing data.
void initInto(TimerList &Dest) const {
if (!BuildDefs::dump())
return;
@@ -135,8 +136,8 @@
}
};
- // ThreadContext contains thread-local data. This data can be
- // combined/reduced as needed after all threads complete.
+ /// ThreadContext contains thread-local data. This data can be
+ /// combined/reduced as needed after all threads complete.
class ThreadContext {
ThreadContext(const ThreadContext &) = delete;
ThreadContext &operator=(const ThreadContext &) = delete;
@@ -149,24 +150,24 @@
};
public:
- // The dump stream is a log stream while emit is the stream code
- // is emitted to. The error stream is strictly for logging errors.
+ /// The dump stream is a log stream while emit is the stream code
+ /// is emitted to. The error stream is strictly for logging errors.
GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError,
ELFStreamer *ELFStreamer, const ClFlags &Flags);
~GlobalContext();
- //
- // The dump, error, and emit streams need to be used by only one
- // thread at a time. This is done by exclusively reserving the
- // streams via lockStr() and unlockStr(). The OstreamLocker class
- // can be used to conveniently manage this.
- //
- // The model is that a thread grabs the stream lock, then does an
- // arbitrary amount of work during which far-away callees may grab
- // the stream and do something with it, and finally the thread
- // releases the stream lock. This allows large chunks of output to
- // be dumped or emitted without risking interleaving from multiple
- // threads.
+ ///
+ /// The dump, error, and emit streams need to be used by only one
+ /// thread at a time. This is done by exclusively reserving the
+ /// streams via lockStr() and unlockStr(). The OstreamLocker class
+ /// can be used to conveniently manage this.
+ ///
+ /// The model is that a thread grabs the stream lock, then does an
+ /// arbitrary amount of work during which far-away callees may grab
+ /// the stream and do something with it, and finally the thread
+ /// releases the stream lock. This allows large chunks of output to
+ /// be dumped or emitted without risking interleaving from multiple
+ /// threads.
void lockStr() { StrLock.lock(); }
void unlockStr() { StrLock.unlock(); }
Ostream &getStrDump() { return *StrDump; }
@@ -177,10 +178,10 @@
return LockedPtr<ErrorCode>(&ErrorStatus, &ErrorStatusLock);
}
- // When emitting assembly, we allow a string to be prepended to
- // names of translated functions. This makes it easier to create an
- // execution test against a reference translator like llc, with both
- // translators using the same bitcode as input.
+ /// When emitting assembly, we allow a string to be prepended to
+ /// names of translated functions. This makes it easier to create an
+ /// execution test against a reference translator like llc, with both
+ /// translators using the same bitcode as input.
IceString mangleName(const IceString &Name) const;
// Manage Constants.
@@ -194,18 +195,18 @@
Constant *getConstantInt64(int64_t ConstantInt64);
Constant *getConstantFloat(float Value);
Constant *getConstantDouble(double Value);
- // Returns a symbolic constant.
+ /// Returns a symbolic constant.
Constant *getConstantSym(RelocOffsetT Offset, const IceString &Name,
bool SuppressMangling);
Constant *getConstantExternSym(const IceString &Name);
- // Returns an undef.
+ /// Returns an undef.
Constant *getConstantUndef(Type Ty);
- // Returns a zero value.
+ /// Returns a zero value.
Constant *getConstantZero(Type Ty);
- // getConstantPool() returns a copy of the constant pool for
- // constants of a given type.
+ /// getConstantPool() returns a copy of the constant pool for
+ /// constants of a given type.
ConstantList getConstantPool(Type Ty);
- // Returns a copy of the list of external symbols.
+ /// Returns a copy of the list of external symbols.
ConstantList getConstantExternSyms();
const ClFlags &getFlags() const { return Flags; }
@@ -214,11 +215,11 @@
return getFlags().getDisableIRGeneration();
}
- // Allocate data of type T using the global allocator. We allow entities
- // allocated from this global allocator to be either trivially or
- // non-trivially destructible. We optimize the case when T is trivially
- // destructible by not registering a destructor. Destructors will be invoked
- // during GlobalContext destruction in the reverse object creation order.
+ /// Allocate data of type T using the global allocator. We allow entities
+ /// allocated from this global allocator to be either trivially or
+ /// non-trivially destructible. We optimize the case when T is trivially
+ /// destructible by not registering a destructor. Destructors will be invoked
+ /// during GlobalContext destruction in the reverse object creation order.
template <typename T>
typename std::enable_if<std::is_trivially_destructible<T>::value, T>::type *
allocate() {
@@ -241,7 +242,7 @@
ELFObjectWriter *getObjectWriter() const { return ObjectWriter.get(); }
- // Reset stats at the beginning of a function.
+ /// Reset stats at the beginning of a function.
void resetStats() {
if (BuildDefs::dump())
ICE_TLS_GET_FIELD(TLS)->StatsFunction.reset();
@@ -283,7 +284,7 @@
Tls->StatsCumulative.update(CodeStats::CS_NumFills);
}
- // Number of Randomized or Pooled Immediates
+ /// Number of Randomized or Pooled Immediates
void statsUpdateRPImms() {
if (!getFlags().getDumpStats())
return;
@@ -292,44 +293,44 @@
Tls->StatsCumulative.update(CodeStats::CS_NumRPImms);
}
- // These are predefined TimerStackIdT values.
+ /// These are predefined TimerStackIdT values.
enum TimerStackKind { TSK_Default = 0, TSK_Funcs, TSK_Num };
- // newTimerStackID() creates a new TimerStack in the global space.
- // It does not affect any TimerStack objects in TLS.
+ /// newTimerStackID() creates a new TimerStack in the global space.
+ /// It does not affect any TimerStack objects in TLS.
TimerStackIdT newTimerStackID(const IceString &Name);
- // dumpTimers() dumps the global timer data. As such, one probably
- // wants to call mergeTimerStacks() as a prerequisite.
+ /// dumpTimers() dumps the global timer data. As such, one probably
+ /// wants to call mergeTimerStacks() as a prerequisite.
void dumpTimers(TimerStackIdT StackID = TSK_Default,
bool DumpCumulative = true);
- // The following methods affect only the calling thread's TLS timer
- // data.
+ /// The following methods affect only the calling thread's TLS timer
+ /// data.
TimerIdT getTimerID(TimerStackIdT StackID, const IceString &Name);
void pushTimer(TimerIdT ID, TimerStackIdT StackID);
void popTimer(TimerIdT ID, TimerStackIdT StackID);
void resetTimer(TimerStackIdT StackID);
void setTimerName(TimerStackIdT StackID, const IceString &NewName);
- // This is the first work item sequence number that the parser
- // produces, and correspondingly the first sequence number that the
- // emitter thread will wait for. Start numbering at 1 to leave room
- // for a sentinel, in case e.g. we wish to inject items with a
- // special sequence number that may be executed out of order.
+ /// This is the first work item sequence number that the parser
+ /// produces, and correspondingly the first sequence number that the
+ /// emitter thread will wait for. Start numbering at 1 to leave room
+ /// for a sentinel, in case e.g. we wish to inject items with a
+ /// special sequence number that may be executed out of order.
static uint32_t getFirstSequenceNumber() { return 1; }
- // Adds a newly parsed and constructed function to the Cfg work
- // queue. Notifies any idle workers that a new function is
- // available for translating. May block if the work queue is too
- // large, in order to control memory footprint.
+ /// Adds a newly parsed and constructed function to the Cfg work
+ /// queue. Notifies any idle workers that a new function is
+ /// available for translating. May block if the work queue is too
+ /// large, in order to control memory footprint.
void optQueueBlockingPush(std::unique_ptr<Cfg> Func);
- // Takes a Cfg from the work queue for translating. May block if
- // the work queue is currently empty. Returns nullptr if there is
- // no more work - the queue is empty and either end() has been
- // called or the Sequential flag was set.
+ /// Takes a Cfg from the work queue for translating. May block if
+ /// the work queue is currently empty. Returns nullptr if there is
+ /// no more work - the queue is empty and either end() has been
+ /// called or the Sequential flag was set.
std::unique_ptr<Cfg> optQueueBlockingPop();
- // Notifies that no more work will be added to the work queue.
+ /// Notifies that no more work will be added to the work queue.
void optQueueNotifyEnd() { OptQ.notifyEnd(); }
- // Emit file header for output file.
+ /// Emit file header for output file.
void emitFileHeader();
void lowerConstants();
@@ -394,44 +395,44 @@
}
}
- // Translation thread startup routine.
+ /// Translation thread startup routine.
void translateFunctionsWrapper(ThreadContext *MyTLS) {
ICE_TLS_SET_FIELD(TLS, MyTLS);
translateFunctions();
}
- // Translate functions from the Cfg queue until the queue is empty.
+ /// Translate functions from the Cfg queue until the queue is empty.
void translateFunctions();
- // Emitter thread startup routine.
+ /// Emitter thread startup routine.
void emitterWrapper(ThreadContext *MyTLS) {
ICE_TLS_SET_FIELD(TLS, MyTLS);
emitItems();
}
- // Emit functions and global initializers from the emitter queue
- // until the queue is empty.
+ /// Emit functions and global initializers from the emitter queue
+ /// until the queue is empty.
void emitItems();
- // Uses DataLowering to lower Globals. Side effects:
- // - discards the initializer list for the global variable in Globals.
- // - clears the Globals array.
+ /// Uses DataLowering to lower Globals. Side effects:
+ /// - discards the initializer list for the global variable in Globals.
+ /// - clears the Globals array.
void lowerGlobals(const IceString &SectionSuffix);
- // Lowers the profile information.
+ /// Lowers the profile information.
void lowerProfileData();
- // Utility function to match a symbol name against a match string.
- // This is used in a few cases where we want to take some action on
- // a particular function or symbol based on a command-line argument,
- // such as changing the verbose level for a particular function. An
- // empty Match argument means match everything. Returns true if
- // there is a match.
+ /// Utility function to match a symbol name against a match string.
+ /// This is used in a few cases where we want to take some action on
+ /// a particular function or symbol based on a command-line argument,
+ /// such as changing the verbose level for a particular function. An
+ /// empty Match argument means match everything. Returns true if
+ /// there is a match.
static bool matchSymbolName(const IceString &SymbolName,
const IceString &Match) {
return Match.empty() || Match == SymbolName;
}
- // Return the randomization cookie for diversification.
- // Initialize the cookie if necessary
+ /// Return the randomization cookie for diversification.
+ /// Initialize the cookie if necessary
uint32_t getRandomizationCookie() const { return RandomizationCookie; }
private:
@@ -470,12 +471,12 @@
TimerList Timers;
ICE_CACHELINE_BOUNDARY;
- // StrLock is a global lock on the dump and emit output streams.
+ /// StrLock is a global lock on the dump and emit output streams.
typedef std::mutex StrLockType;
StrLockType StrLock;
- Ostream *StrDump; // Stream for dumping / diagnostics
- Ostream *StrEmit; // Stream for code emission
- Ostream *StrError; // Stream for logging errors.
+ Ostream *StrDump; /// Stream for dumping / diagnostics
+ Ostream *StrEmit; /// Stream for code emission
+ Ostream *StrError; /// Stream for logging errors.
ICE_CACHELINE_BOUNDARY;
@@ -490,8 +491,8 @@
// emitItems(), or in IceCompiler::run before the compilation is over.)
// TODO(jpp): move to EmitterContext.
std::unique_ptr<TargetDataLowering> DataLowering;
- // If !HasEmittedCode, SubZero will accumulate all Globals (which are "true"
- // program global variables) until the first code WorkItem is seen.
+ /// If !HasEmittedCode, SubZero will accumulate all Globals (which are "true"
+ /// program global variables) until the first code WorkItem is seen.
// TODO(jpp): move to EmitterContext.
bool HasSeenCode = false;
// TODO(jpp): move to EmitterContext.
@@ -548,9 +549,9 @@
static void TlsInit() { ICE_TLS_INIT_FIELD(TLS); }
};
-// Helper class to push and pop a timer marker. The constructor
-// pushes a marker, and the destructor pops it. This is for
-// convenient timing of regions of code.
+/// Helper class to push and pop a timer marker. The constructor
+/// pushes a marker, and the destructor pops it. This is for
+/// convenient timing of regions of code.
class TimerMarker {
TimerMarker() = delete;
TimerMarker(const TimerMarker &) = delete;
@@ -585,8 +586,8 @@
bool Active = false;
};
-// Helper class for locking the streams and then automatically
-// unlocking them.
+/// Helper class for locking the streams and then automatically
+/// unlocking them.
class OstreamLocker {
private:
OstreamLocker() = delete;
diff --git a/src/IceGlobalInits.cpp b/src/IceGlobalInits.cpp
index 1b5085c..c95456c 100644
--- a/src/IceGlobalInits.cpp
+++ b/src/IceGlobalInits.cpp
@@ -6,11 +6,12 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the notion of function declarations, global
-// variable declarations, and the corresponding variable initializers
-// in Subzero.
-//
+///
+/// \file
+/// This file implements the notion of function declarations, global
+/// variable declarations, and the corresponding variable initializers
+/// in Subzero.
+///
//===----------------------------------------------------------------------===//
#include "IceGlobalInits.h"
diff --git a/src/IceGlobalInits.h b/src/IceGlobalInits.h
index 08f4fe3..fb86f7c 100644
--- a/src/IceGlobalInits.h
+++ b/src/IceGlobalInits.h
@@ -6,12 +6,13 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the representation of function declarations,
-// global variable declarations, and the corresponding variable
-// initializers in Subzero. Global variable initializers are
-// represented as a sequence of simple initializers.
-//
+///
+/// \file
+/// This file declares the representation of function declarations,
+/// global variable declarations, and the corresponding variable
+/// initializers in Subzero. Global variable initializers are
+/// represented as a sequence of simple initializers.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEGLOBALINITS_H
@@ -79,8 +80,8 @@
/// Returns true if when emitting names, we should suppress mangling.
virtual bool getSuppressMangling() const = 0;
- // Mangles name for cross tests, unless external and not defined locally
- // (so that relocations accross pnacl-sz and pnacl-llc will work).
+ /// Mangles name for cross tests, unless external and not defined locally
+ /// (so that relocations accross pnacl-sz and pnacl-llc will work).
virtual IceString mangleName(GlobalContext *Ctx) const {
return getSuppressMangling() ? Name : Ctx->mangleName(Name);
}
@@ -95,8 +96,8 @@
llvm::GlobalValue::LinkageTypes Linkage;
};
-// Models a function declaration. This includes the type signature of
-// the function, its calling conventions, and its linkage.
+/// Models a function declaration. This includes the type signature of
+/// the function, its calling conventions, and its linkage.
class FunctionDeclaration : public GlobalDeclaration {
FunctionDeclaration() = delete;
FunctionDeclaration(const FunctionDeclaration &) = delete;
@@ -113,7 +114,7 @@
}
const FuncSigType &getSignature() const { return Signature; }
llvm::CallingConv::ID getCallingConv() const { return CallingConv; }
- // isProto implies that there isn't a (local) definition for the function.
+ /// isProto implies that there isn't a (local) definition for the function.
bool isProto() const { return IsProto; }
static bool classof(const GlobalDeclaration *Addr) {
return Addr->getKind() == FunctionDeclarationKind;
@@ -169,7 +170,7 @@
const InitializerKind Kind;
};
- // Models the data in a data initializer.
+ /// Models the data in a data initializer.
typedef std::vector<char> DataVecType;
/// Defines a sequence of byte values as a data initializer.
@@ -205,7 +206,7 @@
Contents[i] = Str[i];
}
- // The byte contents of the data initializer.
+ /// The byte contents of the data initializer.
DataVecType Contents;
};
@@ -230,7 +231,7 @@
explicit ZeroInitializer(SizeT Size)
: Initializer(ZeroInitializerKind), Size(Size) {}
- // The number of bytes to be zero initialized.
+ /// The number of bytes to be zero initialized.
SizeT Size;
};
@@ -262,7 +263,7 @@
Offset(Offset) {} // The global declaration used in the relocation.
const GlobalDeclaration *Declaration;
- // The offset to add to the relocation.
+ /// The offset to add to the relocation.
const RelocOffsetT Offset;
};
@@ -324,14 +325,14 @@
void discardInitializers() { Initializers = nullptr; }
private:
- // list of initializers for the declared variable.
+ /// List of initializers for the declared variable.
std::unique_ptr<InitializerListType> Initializers;
bool HasInitializer;
- // The alignment of the declared variable.
+ /// The alignment of the declared variable.
uint32_t Alignment;
- // True if a declared (global) constant.
+ /// True if a declared (global) constant.
bool IsConstant;
- // If set to true, force getSuppressMangling() to return true.
+ /// If set to true, force getSuppressMangling() to return true.
bool ForceSuppressMangling;
VariableDeclaration()
diff --git a/src/IceInst.cpp b/src/IceInst.cpp
index 317232a..ecfb1b6 100644
--- a/src/IceInst.cpp
+++ b/src/IceInst.cpp
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the Inst class, primarily the various
-// subclass constructors and dump routines.
-//
+///
+/// \file
+/// This file implements the Inst class, primarily the various
+/// subclass constructors and dump routines.
+///
//===----------------------------------------------------------------------===//
#include "IceInst.h"
diff --git a/src/IceInst.h b/src/IceInst.h
index 7aad054..cfa6dd3 100644
--- a/src/IceInst.h
+++ b/src/IceInst.h
@@ -6,11 +6,12 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the Inst class and its target-independent
-// subclasses, which represent the high-level Vanilla ICE instructions
-// and map roughly 1:1 to LLVM instructions.
-//
+///
+/// \file
+/// This file declares the Inst class and its target-independent
+/// subclasses, which represent the high-level Vanilla ICE instructions
+/// and map roughly 1:1 to LLVM instructions.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEINST_H
@@ -31,10 +32,10 @@
namespace Ice {
-// Base instruction class for ICE. Inst has two subclasses:
-// InstHighLevel and InstTarget. High-level ICE instructions inherit
-// from InstHighLevel, and low-level (target-specific) ICE
-// instructions inherit from InstTarget.
+/// Base instruction class for ICE. Inst has two subclasses:
+/// InstHighLevel and InstTarget. High-level ICE instructions inherit
+/// from InstHighLevel, and low-level (target-specific) ICE
+/// instructions inherit from InstTarget.
class Inst : public llvm::ilist_node<Inst> {
Inst() = delete;
Inst(const Inst &) = delete;
@@ -105,8 +106,8 @@
bool isLastUse(const Operand *Src) const;
void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn);
- // Returns a list of out-edges corresponding to a terminator
- // instruction, which is the last instruction of the block.
+ /// Returns a list of out-edges corresponding to a terminator
+ /// instruction, which is the last instruction of the block.
virtual NodeList getTerminatorEdges() const {
// All valid terminator instructions override this method. For
// the default implementation, we assert in case some CfgNode
@@ -116,10 +117,10 @@
return NodeList();
}
virtual bool isUnconditionalBranch() const { return false; }
- // If the instruction is a branch-type instruction with OldNode as a
- // target, repoint it to NewNode and return true, otherwise return
- // false. Only repoint one instance, even if the instruction has
- // multiple instances of OldNode as a target.
+ /// If the instruction is a branch-type instruction with OldNode as a
+ /// target, repoint it to NewNode and return true, otherwise return
+ /// false. Only repoint one instance, even if the instruction has
+ /// multiple instances of OldNode as a target.
virtual bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) {
(void)OldNode;
(void)NewNode;
@@ -129,19 +130,19 @@
virtual bool isSimpleAssign() const { return false; }
void livenessLightweight(Cfg *Func, LivenessBV &Live);
- // Calculates liveness for this instruction. Returns true if this
- // instruction is (tentatively) still live and should be retained,
- // and false if this instruction is (tentatively) dead and should be
- // deleted. The decision is tentative until the liveness dataflow
- // algorithm has converged, and then a separate pass permanently
- // deletes dead instructions.
+ /// Calculates liveness for this instruction. Returns true if this
+ /// instruction is (tentatively) still live and should be retained,
+ /// and false if this instruction is (tentatively) dead and should be
+ /// deleted. The decision is tentative until the liveness dataflow
+ /// algorithm has converged, and then a separate pass permanently
+ /// deletes dead instructions.
bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness,
LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd);
- // Get the number of native instructions that this instruction
- // ultimately emits. By default, high-level instructions don't
- // result in any native instructions, and a target-specific
- // instruction results in a single native instruction.
+ /// Get the number of native instructions that this instruction
+ /// ultimately emits. By default, high-level instructions don't
+ /// result in any native instructions, and a target-specific
+ /// instruction results in a single native instruction.
virtual uint32_t getEmitInstCount() const { return 0; }
// TODO(stichnot): Change Inst back to abstract once the g++ build
// issue is fixed. llvm::ilist<Ice::Inst> doesn't work under g++
@@ -179,26 +180,26 @@
LiveRangesEnded |= (((LREndedBits)1u) << VarIndex);
}
void resetLastUses() { LiveRangesEnded = 0; }
- // The destroy() method lets the instruction cleanly release any
- // memory that was allocated via the Cfg's allocator.
+ /// The destroy() method lets the instruction cleanly release any
+ /// memory that was allocated via the Cfg's allocator.
virtual void destroy(Cfg *Func) { Func->deallocateArrayOf<Operand *>(Srcs); }
const InstKind Kind;
- // Number is the instruction number for describing live ranges.
+ /// Number is the instruction number for describing live ranges.
InstNumberT Number;
- // Deleted means irrevocably deleted.
+ /// Deleted means irrevocably deleted.
bool Deleted = false;
- // Dead means one of two things depending on context: (1) pending
- // deletion after liveness analysis converges, or (2) marked for
- // deletion during lowering due to a folded bool operation.
+ /// Dead means one of two things depending on context: (1) pending
+ /// deletion after liveness analysis converges, or (2) marked for
+ /// deletion during lowering due to a folded bool operation.
bool Dead = false;
- // HasSideEffects means the instruction is something like a function
- // call or a volatile load that can't be removed even if its Dest
- // variable is not live.
+ /// HasSideEffects means the instruction is something like a function
+ /// call or a volatile load that can't be removed even if its Dest
+ /// variable is not live.
bool HasSideEffects = false;
- // IsDestNonKillable means that liveness analysis shouldn't consider
- // this instruction to kill the Dest variable. This is used when
- // lowering produces two assignments to the same variable.
+ /// IsDestNonKillable means that liveness analysis shouldn't consider
+ /// this instruction to kill the Dest variable. This is used when
+ /// lowering produces two assignments to the same variable.
bool IsDestNonKillable = false;
Variable *Dest;
@@ -206,15 +207,15 @@
SizeT NumSrcs = 0;
Operand **Srcs;
- // LiveRangesEnded marks which Variables' live ranges end in this
- // instruction. An instruction can have an arbitrary number of
- // source operands (e.g. a call instruction), and each source
- // operand can contain 0 or 1 Variable (and target-specific operands
- // could contain more than 1 Variable). All the variables in an
- // instruction are conceptually flattened and each variable is
- // mapped to one bit position of the LiveRangesEnded bit vector.
- // Only the first CHAR_BIT * sizeof(LREndedBits) variables are
- // tracked this way.
+ /// LiveRangesEnded marks which Variables' live ranges end in this
+ /// instruction. An instruction can have an arbitrary number of
+ /// source operands (e.g. a call instruction), and each source
+ /// operand can contain 0 or 1 Variable (and target-specific operands
+ /// could contain more than 1 Variable). All the variables in an
+ /// instruction are conceptually flattened and each variable is
+ /// mapped to one bit position of the LiveRangesEnded bit vector.
+ /// Only the first CHAR_BIT * sizeof(LREndedBits) variables are
+ /// tracked this way.
typedef uint32_t LREndedBits; // only first 32 src operands tracked, sorry
LREndedBits LiveRangesEnded;
};
@@ -235,9 +236,9 @@
}
};
-// Alloca instruction. This captures the size in bytes as getSrc(0),
-// and the required alignment in bytes. The alignment must be either
-// 0 (no alignment required) or a power of 2.
+/// Alloca instruction. This captures the size in bytes as getSrc(0),
+/// and the required alignment in bytes. The alignment must be either
+/// 0 (no alignment required) or a power of 2.
class InstAlloca : public InstHighLevel {
InstAlloca() = delete;
InstAlloca(const InstAlloca &) = delete;
@@ -261,8 +262,8 @@
const uint32_t AlignInBytes;
};
-// Binary arithmetic instruction. The source operands are captured in
-// getSrc(0) and getSrc(1).
+/// Binary arithmetic instruction. The source operands are captured in
+/// getSrc(0) and getSrc(1).
class InstArithmetic : public InstHighLevel {
InstArithmetic() = delete;
InstArithmetic(const InstArithmetic &) = delete;
@@ -296,12 +297,12 @@
const OpKind Op;
};
-// Assignment instruction. The source operand is captured in
-// getSrc(0). This is not part of the LLVM bitcode, but is a useful
-// abstraction for some of the lowering. E.g., if Phi instruction
-// lowering happens before target lowering, or for representing an
-// Inttoptr instruction, or as an intermediate step for lowering a
-// Load instruction.
+/// Assignment instruction. The source operand is captured in
+/// getSrc(0). This is not part of the LLVM bitcode, but is a useful
+/// abstraction for some of the lowering. E.g., if Phi instruction
+/// lowering happens before target lowering, or for representing an
+/// Inttoptr instruction, or as an intermediate step for lowering a
+/// Load instruction.
class InstAssign : public InstHighLevel {
InstAssign() = delete;
InstAssign(const InstAssign &) = delete;
@@ -319,22 +320,22 @@
InstAssign(Cfg *Func, Variable *Dest, Operand *Source);
};
-// Branch instruction. This represents both conditional and
-// unconditional branches.
+/// Branch instruction. This represents both conditional and
+/// unconditional branches.
class InstBr : public InstHighLevel {
InstBr() = delete;
InstBr(const InstBr &) = delete;
InstBr &operator=(const InstBr &) = delete;
public:
- // Create a conditional branch. If TargetTrue==TargetFalse, it is
- // optimized to an unconditional branch.
+ /// Create a conditional branch. If TargetTrue==TargetFalse, it is
+ /// optimized to an unconditional branch.
static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue,
CfgNode *TargetFalse) {
return new (Func->allocate<InstBr>())
InstBr(Func, Source, TargetTrue, TargetFalse);
}
- // Create an unconditional branch.
+ /// Create an unconditional branch.
static InstBr *create(Cfg *Func, CfgNode *Target) {
return new (Func->allocate<InstBr>()) InstBr(Func, Target);
}
@@ -356,17 +357,17 @@
static bool classof(const Inst *Inst) { return Inst->getKind() == Br; }
private:
- // Conditional branch
+ /// Conditional branch
InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse);
- // Unconditional branch
+ /// Unconditional branch
InstBr(Cfg *Func, CfgNode *Target);
- CfgNode *TargetFalse; // Doubles as unconditional branch target
- CfgNode *TargetTrue; // nullptr if unconditional branch
+ CfgNode *TargetFalse; /// Doubles as unconditional branch target
+ CfgNode *TargetTrue; /// nullptr if unconditional branch
};
-// Call instruction. The call target is captured as getSrc(0), and
-// arg I is captured as getSrc(I+1).
+/// Call instruction. The call target is captured as getSrc(0), and
+/// arg I is captured as getSrc(I+1).
class InstCall : public InstHighLevel {
InstCall() = delete;
InstCall(const InstCall &) = delete;
@@ -375,9 +376,9 @@
public:
static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
Operand *CallTarget, bool HasTailCall) {
- // Set HasSideEffects to true so that the call instruction can't be
- // dead-code eliminated. IntrinsicCalls can override this if the
- // particular intrinsic is deletable and has no side-effects.
+ /// Set HasSideEffects to true so that the call instruction can't be
+ /// dead-code eliminated. IntrinsicCalls can override this if the
+ /// particular intrinsic is deletable and has no side-effects.
const bool HasSideEffects = true;
const InstKind Kind = Inst::Call;
return new (Func->allocate<InstCall>()) InstCall(
@@ -404,7 +405,7 @@
bool HasTailCall;
};
-// Cast instruction (a.k.a. conversion operation).
+/// Cast instruction (a.k.a. conversion operation).
class InstCast : public InstHighLevel {
InstCast() = delete;
InstCast(const InstCast &) = delete;
@@ -435,7 +436,7 @@
const OpKind CastKind;
};
-// ExtractElement instruction.
+/// ExtractElement instruction.
class InstExtractElement : public InstHighLevel {
InstExtractElement() = delete;
InstExtractElement(const InstExtractElement &) = delete;
@@ -458,8 +459,8 @@
Operand *Source2);
};
-// Floating-point comparison instruction. The source operands are
-// captured in getSrc(0) and getSrc(1).
+/// Floating-point comparison instruction. The source operands are
+/// captured in getSrc(0) and getSrc(1).
class InstFcmp : public InstHighLevel {
InstFcmp() = delete;
InstFcmp(const InstFcmp &) = delete;
@@ -489,8 +490,8 @@
const FCond Condition;
};
-// Integer comparison instruction. The source operands are captured
-// in getSrc(0) and getSrc(1).
+/// Integer comparison instruction. The source operands are captured
+/// in getSrc(0) and getSrc(1).
class InstIcmp : public InstHighLevel {
InstIcmp() = delete;
InstIcmp(const InstIcmp &) = delete;
@@ -520,7 +521,7 @@
const ICond Condition;
};
-// InsertElement instruction.
+/// InsertElement instruction.
class InstInsertElement : public InstHighLevel {
InstInsertElement() = delete;
InstInsertElement(const InstInsertElement &) = delete;
@@ -543,8 +544,8 @@
Operand *Source2, Operand *Source3);
};
-// Call to an intrinsic function. The call target is captured as getSrc(0),
-// and arg I is captured as getSrc(I+1).
+/// Call to an intrinsic function. The call target is captured as getSrc(0),
+/// and arg I is captured as getSrc(I+1).
class InstIntrinsicCall : public InstCall {
InstIntrinsicCall() = delete;
InstIntrinsicCall(const InstIntrinsicCall &) = delete;
@@ -573,7 +574,7 @@
const Intrinsics::IntrinsicInfo Info;
};
-// Load instruction. The source address is captured in getSrc(0).
+/// Load instruction. The source address is captured in getSrc(0).
class InstLoad : public InstHighLevel {
InstLoad() = delete;
InstLoad(const InstLoad &) = delete;
@@ -594,8 +595,8 @@
InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr);
};
-// Phi instruction. For incoming edge I, the node is Labels[I] and
-// the Phi source operand is getSrc(I).
+/// Phi instruction. For incoming edge I, the node is Labels[I] and
+/// the Phi source operand is getSrc(I).
class InstPhi : public InstHighLevel {
InstPhi() = delete;
InstPhi(const InstPhi &) = delete;
@@ -621,15 +622,15 @@
Inst::destroy(Func);
}
- // Labels[] duplicates the InEdges[] information in the enclosing
- // CfgNode, but the Phi instruction is created before InEdges[]
- // is available, so it's more complicated to share the list.
+ /// Labels[] duplicates the InEdges[] information in the enclosing
+ /// CfgNode, but the Phi instruction is created before InEdges[]
+ /// is available, so it's more complicated to share the list.
CfgNode **Labels;
};
-// Ret instruction. The return value is captured in getSrc(0), but if
-// there is no return value (void-type function), then
-// getSrcSize()==0 and hasRetValue()==false.
+/// Ret instruction. The return value is captured in getSrc(0), but if
+/// there is no return value (void-type function), then
+/// getSrcSize()==0 and hasRetValue()==false.
class InstRet : public InstHighLevel {
InstRet() = delete;
InstRet(const InstRet &) = delete;
@@ -652,7 +653,7 @@
InstRet(Cfg *Func, Operand *RetValue);
};
-// Select instruction. The condition, true, and false operands are captured.
+/// Select instruction. The condition, true, and false operands are captured.
class InstSelect : public InstHighLevel {
InstSelect() = delete;
InstSelect(const InstSelect &) = delete;
@@ -675,8 +676,8 @@
Operand *Source2);
};
-// Store instruction. The address operand is captured, along with the
-// data operand to be stored into the address.
+/// Store instruction. The address operand is captured, along with the
+/// data operand to be stored into the address.
class InstStore : public InstHighLevel {
InstStore() = delete;
InstStore(const InstStore &) = delete;
@@ -700,8 +701,8 @@
InstStore(Cfg *Func, Operand *Data, Operand *Addr);
};
-// Switch instruction. The single source operand is captured as
-// getSrc(0).
+/// Switch instruction. The single source operand is captured as
+/// getSrc(0).
class InstSwitch : public InstHighLevel {
InstSwitch() = delete;
InstSwitch(const InstSwitch &) = delete;
@@ -739,13 +740,13 @@
}
CfgNode *LabelDefault;
- SizeT NumCases; // not including the default case
- uint64_t *Values; // size is NumCases
- CfgNode **Labels; // size is NumCases
+ SizeT NumCases; /// not including the default case
+ uint64_t *Values; /// size is NumCases
+ CfgNode **Labels; /// size is NumCases
};
-// Unreachable instruction. This is a terminator instruction with no
-// operands.
+/// Unreachable instruction. This is a terminator instruction with no
+/// operands.
class InstUnreachable : public InstHighLevel {
InstUnreachable() = delete;
InstUnreachable(const InstUnreachable &) = delete;
@@ -765,8 +766,8 @@
explicit InstUnreachable(Cfg *Func);
};
-// BundleLock instruction. There are no operands. Contains an option
-// indicating whether align_to_end is specified.
+/// BundleLock instruction. There are no operands. Contains an option
+/// indicating whether align_to_end is specified.
class InstBundleLock : public InstHighLevel {
InstBundleLock() = delete;
InstBundleLock(const InstBundleLock &) = delete;
@@ -791,7 +792,7 @@
InstBundleLock(Cfg *Func, Option BundleOption);
};
-// BundleUnlock instruction. There are no operands.
+/// BundleUnlock instruction. There are no operands.
class InstBundleUnlock : public InstHighLevel {
InstBundleUnlock() = delete;
InstBundleUnlock(const InstBundleUnlock &) = delete;
@@ -812,18 +813,18 @@
explicit InstBundleUnlock(Cfg *Func);
};
-// FakeDef instruction. This creates a fake definition of a variable,
-// which is how we represent the case when an instruction produces
-// multiple results. This doesn't happen with high-level ICE
-// instructions, but might with lowered instructions. For example,
-// this would be a way to represent condition flags being modified by
-// an instruction.
-//
-// It's generally useful to set the optional source operand to be the
-// dest variable of the instruction that actually produces the FakeDef
-// dest. Otherwise, the original instruction could be dead-code
-// eliminated if its dest operand is unused, and therefore the FakeDef
-// dest wouldn't be properly initialized.
+/// FakeDef instruction. This creates a fake definition of a variable,
+/// which is how we represent the case when an instruction produces
+/// multiple results. This doesn't happen with high-level ICE
+/// instructions, but might with lowered instructions. For example,
+/// this would be a way to represent condition flags being modified by
+/// an instruction.
+///
+/// It's generally useful to set the optional source operand to be the
+/// dest variable of the instruction that actually produces the FakeDef
+/// dest. Otherwise, the original instruction could be dead-code
+/// eliminated if its dest operand is unused, and therefore the FakeDef
+/// dest wouldn't be properly initialized.
class InstFakeDef : public InstHighLevel {
InstFakeDef() = delete;
InstFakeDef(const InstFakeDef &) = delete;
@@ -843,11 +844,11 @@
InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src);
};
-// FakeUse instruction. This creates a fake use of a variable, to
-// keep the instruction that produces that variable from being
-// dead-code eliminated. This is useful in a variety of lowering
-// situations. The FakeUse instruction has no dest, so it can itself
-// never be dead-code eliminated.
+/// FakeUse instruction. This creates a fake use of a variable, to
+/// keep the instruction that produces that variable from being
+/// dead-code eliminated. This is useful in a variety of lowering
+/// situations. The FakeUse instruction has no dest, so it can itself
+/// never be dead-code eliminated.
class InstFakeUse : public InstHighLevel {
InstFakeUse() = delete;
InstFakeUse(const InstFakeUse &) = delete;
@@ -866,16 +867,16 @@
InstFakeUse(Cfg *Func, Variable *Src);
};
-// FakeKill instruction. This "kills" a set of variables by modeling
-// a trivial live range at this instruction for each (implicit)
-// variable. The primary use is to indicate that scratch registers
-// are killed after a call, so that the register allocator won't
-// assign a scratch register to a variable whose live range spans a
-// call.
-//
-// The FakeKill instruction also holds a pointer to the instruction
-// that kills the set of variables, so that if that linked instruction
-// gets dead-code eliminated, the FakeKill instruction will as well.
+/// FakeKill instruction. This "kills" a set of variables by modeling
+/// a trivial live range at this instruction for each (implicit)
+/// variable. The primary use is to indicate that scratch registers
+/// are killed after a call, so that the register allocator won't
+/// assign a scratch register to a variable whose live range spans a
+/// call.
+///
+/// The FakeKill instruction also holds a pointer to the instruction
+/// that kills the set of variables, so that if that linked instruction
+/// gets dead-code eliminated, the FakeKill instruction will as well.
class InstFakeKill : public InstHighLevel {
InstFakeKill() = delete;
InstFakeKill(const InstFakeKill &) = delete;
@@ -894,12 +895,12 @@
private:
InstFakeKill(Cfg *Func, const Inst *Linked);
- // This instruction is ignored if Linked->isDeleted() is true.
+ /// This instruction is ignored if Linked->isDeleted() is true.
const Inst *Linked;
};
-// The Target instruction is the base class for all target-specific
-// instructions.
+/// The Target instruction is the base class for all target-specific
+/// instructions.
class InstTarget : public Inst {
InstTarget() = delete;
InstTarget(const InstTarget &) = delete;
@@ -923,8 +924,8 @@
namespace llvm {
-// Override the default ilist traits so that Inst's private ctor and
-// deleted dtor aren't invoked.
+/// Override the default ilist traits so that Inst's private ctor and
+/// deleted dtor aren't invoked.
template <>
struct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> {
Ice::Inst *createSentinel() const {
diff --git a/src/IceInstARM32.cpp b/src/IceInstARM32.cpp
index 0476934..72178ac 100644
--- a/src/IceInstARM32.cpp
+++ b/src/IceInstARM32.cpp
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the InstARM32 and OperandARM32 classes,
-// primarily the constructors and the dump()/emit() methods.
-//
+///
+/// \file
+/// This file implements the InstARM32 and OperandARM32 classes,
+/// primarily the constructors and the dump()/emit() methods.
+///
//===----------------------------------------------------------------------===//
#include "IceInstARM32.h"
diff --git a/src/IceInstARM32.h b/src/IceInstARM32.h
index caef19f..d12c4ff 100644
--- a/src/IceInstARM32.h
+++ b/src/IceInstARM32.h
@@ -6,11 +6,12 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the InstARM32 and OperandARM32 classes and
-// their subclasses. This represents the machine instructions and
-// operands used for ARM32 code selection.
-//
+///
+/// \file
+/// This file declares the InstARM32 and OperandARM32 classes and
+/// their subclasses. This represents the machine instructions and
+/// operands used for ARM32 code selection.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEINSTARM32_H
@@ -26,8 +27,8 @@
class TargetARM32;
-// OperandARM32 extends the Operand hierarchy. Its subclasses are
-// OperandARM32Mem and OperandARM32Flex.
+/// OperandARM32 extends the Operand hierarchy. Its subclasses are
+/// OperandARM32Mem and OperandARM32Flex.
class OperandARM32 : public Operand {
OperandARM32() = delete;
OperandARM32(const OperandARM32 &) = delete;
@@ -61,16 +62,16 @@
: Operand(static_cast<OperandKind>(Kind), Ty) {}
};
-// OperandARM32Mem represents a memory operand in any of the various ARM32
-// addressing modes.
+/// OperandARM32Mem represents a memory operand in any of the various ARM32
+/// addressing modes.
class OperandARM32Mem : public OperandARM32 {
OperandARM32Mem() = delete;
OperandARM32Mem(const OperandARM32Mem &) = delete;
OperandARM32Mem &operator=(const OperandARM32Mem &) = delete;
public:
- // Memory operand addressing mode.
- // The enum value also carries the encoding.
+ /// Memory operand addressing mode.
+ /// The enum value also carries the encoding.
// TODO(jvoung): unify with the assembler.
enum AddrMode {
// bit encoding P U W
@@ -82,21 +83,21 @@
NegPostIndex = (0 | 0 | 0) << 21 // negative post-indexed with writeback
};
- // Provide two constructors.
- // NOTE: The Variable-typed operands have to be registers.
- //
- // (1) Reg + Imm. The Immediate actually has a limited number of bits
- // for encoding, so check canHoldOffset first. It cannot handle
- // general Constant operands like ConstantRelocatable, since a relocatable
- // can potentially take up too many bits.
+ /// Provide two constructors.
+ /// NOTE: The Variable-typed operands have to be registers.
+ ///
+ /// (1) Reg + Imm. The Immediate actually has a limited number of bits
+ /// for encoding, so check canHoldOffset first. It cannot handle
+ /// general Constant operands like ConstantRelocatable, since a relocatable
+ /// can potentially take up too many bits.
static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base,
ConstantInteger32 *ImmOffset,
AddrMode Mode = Offset) {
return new (Func->allocate<OperandARM32Mem>())
OperandARM32Mem(Func, Ty, Base, ImmOffset, Mode);
}
- // (2) Reg +/- Reg with an optional shift of some kind and amount.
- // Note that this mode is disallowed in the NaCl sandbox.
+ /// (2) Reg +/- Reg with an optional shift of some kind and amount.
+ /// Note that this mode is disallowed in the NaCl sandbox.
static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base,
Variable *Index, ShiftKind ShiftOp = kNoShift,
uint16_t ShiftAmt = 0,
@@ -129,10 +130,10 @@
return Operand->getKind() == static_cast<OperandKind>(kMem);
}
- // Return true if a load/store instruction for an element of type Ty
- // can encode the Offset directly in the immediate field of the 32-bit
- // ARM instruction. For some types, if the load is Sign extending, then
- // the range is reduced.
+ /// Return true if a load/store instruction for an element of type Ty
+ /// can encode the Offset directly in the immediate field of the 32-bit
+ /// ARM instruction. For some types, if the load is Sign extending, then
+ /// the range is reduced.
static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset);
private:
@@ -149,10 +150,10 @@
AddrMode Mode;
};
-// OperandARM32Flex represent the "flexible second operand" for
-// data-processing instructions. It can be a rotatable 8-bit constant, or
-// a register with an optional shift operand. The shift amount can even be
-// a third register.
+/// OperandARM32Flex represent the "flexible second operand" for
+/// data-processing instructions. It can be a rotatable 8-bit constant, or
+/// a register with an optional shift operand. The shift amount can even be
+/// a third register.
class OperandARM32Flex : public OperandARM32 {
OperandARM32Flex() = delete;
OperandARM32Flex(const OperandARM32Flex &) = delete;
@@ -168,14 +169,14 @@
OperandARM32Flex(OperandKindARM32 Kind, Type Ty) : OperandARM32(Kind, Ty) {}
};
-// Rotated immediate variant.
+/// Rotated immediate variant.
class OperandARM32FlexImm : public OperandARM32Flex {
OperandARM32FlexImm() = delete;
OperandARM32FlexImm(const OperandARM32FlexImm &) = delete;
OperandARM32FlexImm &operator=(const OperandARM32FlexImm &) = delete;
public:
- // Immed_8 rotated by an even number of bits (2 * RotateAmt).
+ /// Immed_8 rotated by an even number of bits (2 * RotateAmt).
static OperandARM32FlexImm *create(Cfg *Func, Type Ty, uint32_t Imm,
uint32_t RotateAmt) {
return new (Func->allocate<OperandARM32FlexImm>())
@@ -190,8 +191,8 @@
return Operand->getKind() == static_cast<OperandKind>(kFlexImm);
}
- // Return true if the Immediate can fit in the ARM flexible operand.
- // Fills in the out-params RotateAmt and Immed_8 if Immediate fits.
+ /// Return true if the Immediate can fit in the ARM flexible operand.
+ /// Fills in the out-params RotateAmt and Immed_8 if Immediate fits.
static bool canHoldImm(uint32_t Immediate, uint32_t *RotateAmt,
uint32_t *Immed_8);
@@ -205,14 +206,14 @@
uint32_t RotateAmt;
};
-// Shifted register variant.
+/// Shifted register variant.
class OperandARM32FlexReg : public OperandARM32Flex {
OperandARM32FlexReg() = delete;
OperandARM32FlexReg(const OperandARM32FlexReg &) = delete;
OperandARM32FlexReg &operator=(const OperandARM32FlexReg &) = delete;
public:
- // Register with immediate/reg shift amount and shift operation.
+ /// Register with immediate/reg shift amount and shift operation.
static OperandARM32FlexReg *create(Cfg *Func, Type Ty, Variable *Reg,
ShiftKind ShiftOp, Operand *ShiftAmt) {
return new (Func->allocate<OperandARM32FlexReg>())
@@ -229,7 +230,7 @@
Variable *getReg() const { return Reg; }
ShiftKind getShiftOp() const { return ShiftOp; }
- // ShiftAmt can represent an immediate or a register.
+ /// ShiftAmt can represent an immediate or a register.
Operand *getShiftAmt() const { return ShiftAmt; }
private:
@@ -241,9 +242,9 @@
Operand *ShiftAmt;
};
-// Base class for ARM instructions. While most ARM instructions can be
-// conditionally executed, a few of them are not predicable (halt,
-// memory barriers, etc.).
+/// Base class for ARM instructions. While most ARM instructions can be
+/// conditionally executed, a few of them are not predicable (halt,
+/// memory barriers, etc.).
class InstARM32 : public InstTarget {
InstARM32() = delete;
InstARM32(const InstARM32 &) = delete;
@@ -304,7 +305,7 @@
}
};
-// A predicable ARM instruction.
+/// A predicable ARM instruction.
class InstARM32Pred : public InstARM32 {
InstARM32Pred() = delete;
InstARM32Pred(const InstARM32Pred &) = delete;
@@ -321,7 +322,7 @@
static const char *predString(CondARM32::Cond Predicate);
void dumpOpcodePred(Ostream &Str, const char *Opcode, Type Ty) const;
- // Shared emit routines for common forms of instructions.
+ /// Shared emit routines for common forms of instructions.
static void emitUnaryopGPR(const char *Opcode, const InstARM32Pred *Inst,
const Cfg *Func);
static void emitTwoAddr(const char *Opcode, const InstARM32Pred *Inst,
@@ -343,7 +344,7 @@
return Stream;
}
-// Instructions of the form x := op(y).
+/// Instructions of the form x := op(y).
template <InstARM32::InstKindARM32 K>
class InstARM32UnaryopGPR : public InstARM32Pred {
InstARM32UnaryopGPR() = delete;
@@ -387,7 +388,7 @@
static const char *Opcode;
};
-// Instructions of the form x := x op y.
+/// Instructions of the form x := x op y.
template <InstARM32::InstKindARM32 K>
class InstARM32TwoAddrGPR : public InstARM32Pred {
InstARM32TwoAddrGPR() = delete;
@@ -395,7 +396,7 @@
InstARM32TwoAddrGPR &operator=(const InstARM32TwoAddrGPR &) = delete;
public:
- // Dest must be a register.
+ /// Dest must be a register.
static InstARM32TwoAddrGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
CondARM32::Cond Predicate) {
return new (Func->allocate<InstARM32TwoAddrGPR>())
@@ -433,8 +434,8 @@
static const char *Opcode;
};
-// Base class for assignment instructions.
-// These can be tested for redundancy (and elided if redundant).
+/// Base class for assignment instructions.
+/// These can be tested for redundancy (and elided if redundant).
template <InstARM32::InstKindARM32 K>
class InstARM32Movlike : public InstARM32Pred {
InstARM32Movlike() = delete;
@@ -475,8 +476,8 @@
static const char *Opcode;
};
-// Instructions of the form x := y op z. May have the side-effect of setting
-// status flags.
+/// Instructions of the form x := y op z. May have the side-effect of setting
+/// status flags.
template <InstARM32::InstKindARM32 K>
class InstARM32ThreeAddrGPR : public InstARM32Pred {
InstARM32ThreeAddrGPR() = delete;
@@ -484,8 +485,8 @@
InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete;
public:
- // Create an ordinary binary-op instruction like add, and sub.
- // Dest and Src1 must be registers.
+ /// Create an ordinary binary-op instruction like add, and sub.
+ /// Dest and Src1 must be registers.
static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest,
Variable *Src0, Operand *Src1,
CondARM32::Cond Predicate,
@@ -633,12 +634,12 @@
typedef InstARM32ThreeAddrGPR<InstARM32::Sdiv> InstARM32Sdiv;
typedef InstARM32ThreeAddrGPR<InstARM32::Sub> InstARM32Sub;
typedef InstARM32ThreeAddrGPR<InstARM32::Udiv> InstARM32Udiv;
-// Move instruction (variable <- flex). This is more of a pseudo-inst.
-// If var is a register, then we use "mov". If var is stack, then we use
-// "str" to store to the stack.
+/// Move instruction (variable <- flex). This is more of a pseudo-inst.
+/// If var is a register, then we use "mov". If var is stack, then we use
+/// "str" to store to the stack.
typedef InstARM32Movlike<InstARM32::Mov> InstARM32Mov;
-// MovT leaves the bottom bits alone so dest is also a source.
-// This helps indicate that a previous MovW setting dest is not dead code.
+/// MovT leaves the bottom bits alone so dest is also a source.
+/// This helps indicate that a previous MovW setting dest is not dead code.
typedef InstARM32TwoAddrGPR<InstARM32::Movt> InstARM32Movt;
typedef InstARM32UnaryopGPR<InstARM32::Movw> InstARM32Movw;
typedef InstARM32UnaryopGPR<InstARM32::Mvn> InstARM32Mvn;
@@ -677,14 +678,14 @@
SizeT Number; // used for unique label generation.
};
-// Direct branch instruction.
+/// Direct branch instruction.
class InstARM32Br : public InstARM32Pred {
InstARM32Br() = delete;
InstARM32Br(const InstARM32Br &) = delete;
InstARM32Br &operator=(const InstARM32Br &) = delete;
public:
- // Create a conditional branch to one of two nodes.
+ /// Create a conditional branch to one of two nodes.
static InstARM32Br *create(Cfg *Func, CfgNode *TargetTrue,
CfgNode *TargetFalse, CondARM32::Cond Predicate) {
assert(Predicate != CondARM32::AL);
@@ -692,16 +693,16 @@
return new (Func->allocate<InstARM32Br>())
InstARM32Br(Func, TargetTrue, TargetFalse, NoLabel, Predicate);
}
- // Create an unconditional branch to a node.
+ /// Create an unconditional branch to a node.
static InstARM32Br *create(Cfg *Func, CfgNode *Target) {
constexpr CfgNode *NoCondTarget = nullptr;
constexpr InstARM32Label *NoLabel = nullptr;
return new (Func->allocate<InstARM32Br>())
InstARM32Br(Func, NoCondTarget, Target, NoLabel, CondARM32::AL);
}
- // Create a non-terminator conditional branch to a node, with a
- // fallthrough to the next instruction in the current node. This is
- // used for switch lowering.
+ /// Create a non-terminator conditional branch to a node, with a
+ /// fallthrough to the next instruction in the current node. This is
+ /// used for switch lowering.
static InstARM32Br *create(Cfg *Func, CfgNode *Target,
CondARM32::Cond Predicate) {
assert(Predicate != CondARM32::AL);
@@ -750,18 +751,18 @@
const InstARM32Label *Label; // Intra-block branch target
};
-// AdjustStack instruction - subtracts SP by the given amount and
-// updates the stack offset during code emission.
+/// AdjustStack instruction - subtracts SP by the given amount and
+/// updates the stack offset during code emission.
class InstARM32AdjustStack : public InstARM32 {
InstARM32AdjustStack() = delete;
InstARM32AdjustStack(const InstARM32AdjustStack &) = delete;
InstARM32AdjustStack &operator=(const InstARM32AdjustStack &) = delete;
public:
- // Note: We need both Amount and SrcAmount. If Amount is too large then
- // it needs to be copied to a register (so SrcAmount could be a register).
- // However, we also need the numeric Amount for bookkeeping, and it's
- // hard to pull that from the generic SrcAmount operand.
+ /// Note: We need both Amount and SrcAmount. If Amount is too large then
+ /// it needs to be copied to a register (so SrcAmount could be a register).
+ /// However, we also need the numeric Amount for bookkeeping, and it's
+ /// hard to pull that from the generic SrcAmount operand.
static InstARM32AdjustStack *create(Cfg *Func, Variable *SP, SizeT Amount,
Operand *SrcAmount) {
return new (Func->allocate<InstARM32AdjustStack>())
@@ -778,9 +779,9 @@
const SizeT Amount;
};
-// Call instruction (bl/blx). Arguments should have already been pushed.
-// Technically bl and the register form of blx can be predicated, but we'll
-// leave that out until needed.
+/// Call instruction (bl/blx). Arguments should have already been pushed.
+/// Technically bl and the register form of blx can be predicated, but we'll
+/// leave that out until needed.
class InstARM32Call : public InstARM32 {
InstARM32Call() = delete;
InstARM32Call(const InstARM32Call &) = delete;
@@ -801,14 +802,14 @@
InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget);
};
-// Load instruction.
+/// Load instruction.
class InstARM32Ldr : public InstARM32Pred {
InstARM32Ldr() = delete;
InstARM32Ldr(const InstARM32Ldr &) = delete;
InstARM32Ldr &operator=(const InstARM32Ldr &) = delete;
public:
- // Dest must be a register.
+ /// Dest must be a register.
static InstARM32Ldr *create(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem,
CondARM32::Cond Predicate) {
return new (Func->allocate<InstARM32Ldr>())
@@ -824,8 +825,8 @@
CondARM32::Cond Predicate);
};
-// Pop into a list of GPRs. Technically this can be predicated, but we don't
-// need that functionality.
+/// Pop into a list of GPRs. Technically this can be predicated, but we don't
+/// need that functionality.
class InstARM32Pop : public InstARM32 {
InstARM32Pop() = delete;
InstARM32Pop(const InstARM32Pop &) = delete;
@@ -846,8 +847,8 @@
VarList Dests;
};
-// Push a list of GPRs. Technically this can be predicated, but we don't
-// need that functionality.
+/// Push a list of GPRs. Technically this can be predicated, but we don't
+/// need that functionality.
class InstARM32Push : public InstARM32 {
InstARM32Push() = delete;
InstARM32Push(const InstARM32Push &) = delete;
@@ -866,15 +867,15 @@
InstARM32Push(Cfg *Func, const VarList &Srcs);
};
-// Ret pseudo-instruction. This is actually a "bx" instruction with
-// an "lr" register operand, but epilogue lowering will search for a Ret
-// instead of a generic "bx". This instruction also takes a Source
-// operand (for non-void returning functions) for liveness analysis, though
-// a FakeUse before the ret would do just as well.
-//
-// NOTE: Even though "bx" can be predicated, for now leave out the predication
-// since it's not yet known to be useful for Ret. That may complicate finding
-// the terminator instruction if it's not guaranteed to be executed.
+/// Ret pseudo-instruction. This is actually a "bx" instruction with
+/// an "lr" register operand, but epilogue lowering will search for a Ret
+/// instead of a generic "bx". This instruction also takes a Source
+/// operand (for non-void returning functions) for liveness analysis, though
+/// a FakeUse before the ret would do just as well.
+///
+/// NOTE: Even though "bx" can be predicated, for now leave out the predication
+/// since it's not yet known to be useful for Ret. That may complicate finding
+/// the terminator instruction if it's not guaranteed to be executed.
class InstARM32Ret : public InstARM32 {
InstARM32Ret() = delete;
InstARM32Ret(const InstARM32Ret &) = delete;
@@ -894,15 +895,15 @@
InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source);
};
-// Store instruction. It's important for liveness that there is no Dest
-// operand (OperandARM32Mem instead of Dest Variable).
+/// Store instruction. It's important for liveness that there is no Dest
+/// operand (OperandARM32Mem instead of Dest Variable).
class InstARM32Str : public InstARM32Pred {
InstARM32Str() = delete;
InstARM32Str(const InstARM32Str &) = delete;
InstARM32Str &operator=(const InstARM32Str &) = delete;
public:
- // Value must be a register.
+ /// Value must be a register.
static InstARM32Str *create(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
CondARM32::Cond Predicate) {
return new (Func->allocate<InstARM32Str>())
@@ -936,14 +937,14 @@
explicit InstARM32Trap(Cfg *Func);
};
-// Unsigned Multiply Long: d.lo, d.hi := x * y
+/// Unsigned Multiply Long: d.lo, d.hi := x * y
class InstARM32Umull : public InstARM32Pred {
InstARM32Umull() = delete;
InstARM32Umull(const InstARM32Umull &) = delete;
InstARM32Umull &operator=(const InstARM32Umull &) = delete;
public:
- // Everything must be a register.
+ /// Everything must be a register.
static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi,
Variable *Src0, Variable *Src1,
CondARM32::Cond Predicate) {
diff --git a/src/IceInstMIPS32.h b/src/IceInstMIPS32.h
index 0c7c2d8..17c2583 100644
--- a/src/IceInstMIPS32.h
+++ b/src/IceInstMIPS32.h
@@ -6,11 +6,12 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the InstMIPS32 and OperandMIPS32 classes and
-// their subclasses. This represents the machine instructions and
-// operands used for MIPS32 code selection.
-//
+///
+/// \file
+/// This file declares the InstMIPS32 and OperandMIPS32 classes and
+/// their subclasses. This represents the machine instructions and
+/// operands used for MIPS32 code selection.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEINSTMIPS32_H
diff --git a/src/IceInstX8632.cpp b/src/IceInstX8632.cpp
index 2866430..fd33c55 100644
--- a/src/IceInstX8632.cpp
+++ b/src/IceInstX8632.cpp
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the InstX8632 and OperandX8632 classes,
-// primarily the constructors and the dump()/emit() methods.
-//
+///
+/// \file
+/// This file implements the InstX8632 and OperandX8632 classes,
+/// primarily the constructors and the dump()/emit() methods.
+///
//===----------------------------------------------------------------------===//
#include "IceInstX8632.h"
diff --git a/src/IceInstX8632.h b/src/IceInstX8632.h
index 0145293..03a5205 100644
--- a/src/IceInstX8632.h
+++ b/src/IceInstX8632.h
@@ -6,11 +6,12 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the InstX8632 and OperandX8632 classes and
-// their subclasses. This represents the machine instructions and
-// operands used for x86-32 code selection.
-//
+///
+/// \file
+/// This file declares the InstX8632 and OperandX8632 classes and
+/// their subclasses. This represents the machine instructions and
+/// operands used for x86-32 code selection.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEINSTX8632_H
@@ -28,8 +29,8 @@
class TargetX8632;
-// OperandX8632 extends the Operand hierarchy. Its subclasses are
-// OperandX8632Mem and VariableSplit.
+/// OperandX8632 extends the Operand hierarchy. Its subclasses are
+/// OperandX8632Mem and VariableSplit.
class OperandX8632 : public Operand {
OperandX8632() = delete;
OperandX8632(const OperandX8632 &) = delete;
@@ -48,9 +49,9 @@
: Operand(static_cast<OperandKind>(Kind), Ty) {}
};
-// OperandX8632Mem represents the m32 addressing mode, with optional
-// base and index registers, a constant offset, and a fixed shift
-// value for the index register.
+/// OperandX8632Mem represents the m32 addressing mode, with optional
+/// base and index registers, a constant offset, and a fixed shift
+/// value for the index register.
class OperandX8632Mem : public OperandX8632 {
OperandX8632Mem() = delete;
OperandX8632Mem(const OperandX8632Mem &) = delete;
@@ -99,18 +100,18 @@
Variable *Index;
uint16_t Shift;
SegmentRegisters SegmentReg : 16;
- // A flag to show if this memory operand is a randomized one.
- // Randomized memory operands are generated in
- // TargetX8632::randomizeOrPoolImmediate()
+ /// A flag to show if this memory operand is a randomized one.
+ /// Randomized memory operands are generated in
+ /// TargetX8632::randomizeOrPoolImmediate()
bool Randomized;
};
-// VariableSplit is a way to treat an f64 memory location as a pair
-// of i32 locations (Low and High). This is needed for some cases
-// of the Bitcast instruction. Since it's not possible for integer
-// registers to access the XMM registers and vice versa, the
-// lowering forces the f64 to be spilled to the stack and then
-// accesses through the VariableSplit.
+/// VariableSplit is a way to treat an f64 memory location as a pair
+/// of i32 locations (Low and High). This is needed for some cases
+/// of the Bitcast instruction. Since it's not possible for integer
+/// registers to access the XMM registers and vice versa, the
+/// lowering forces the f64 to be spilled to the stack and then
+/// accesses through the VariableSplit.
class VariableSplit : public OperandX8632 {
VariableSplit() = delete;
VariableSplit(const VariableSplit &) = delete;
@@ -145,11 +146,11 @@
Portion Part;
};
-// SpillVariable decorates a Variable by linking it to another
-// Variable. When stack frame offsets are computed, the SpillVariable
-// is given a distinct stack slot only if its linked Variable has a
-// register. If the linked Variable has a stack slot, then the
-// Variable and SpillVariable share that slot.
+/// SpillVariable decorates a Variable by linking it to another
+/// Variable. When stack frame offsets are computed, the SpillVariable
+/// is given a distinct stack slot only if its linked Variable has a
+/// register. If the linked Variable has a stack slot, then the
+/// Variable and SpillVariable share that slot.
class SpillVariable : public Variable {
SpillVariable() = delete;
SpillVariable(const SpillVariable &) = delete;
@@ -284,9 +285,9 @@
getOppositeCondition(X8632::Traits::Cond::BrCond Cond);
void dump(const Cfg *Func) const override;
- // Shared emit routines for common forms of instructions.
- // See the definition of emitTwoAddress() for a description of
- // ShiftHack.
+ /// Shared emit routines for common forms of instructions.
+ /// See the definition of emitTwoAddress() for a description of
+ /// ShiftHack.
static void emitTwoAddress(const char *Opcode, const Inst *Inst,
const Cfg *Func, bool ShiftHack = false);
@@ -302,16 +303,16 @@
static bool isClassof(const Inst *Inst, InstKindX8632 MyKind) {
return Inst->getKind() == static_cast<InstKind>(MyKind);
}
- // Most instructions that operate on vector arguments require vector
- // memory operands to be fully aligned (16-byte alignment for PNaCl
- // vector types). The stack frame layout and call ABI ensure proper
- // alignment for stack operands, but memory operands (originating
- // from load/store bitcode instructions) only have element-size
- // alignment guarantees. This function validates that none of the
- // operands is a memory operand of vector type, calling
- // report_fatal_error() if one is found. This function should be
- // called during emission, and maybe also in the ctor (as long as
- // that fits the lowering style).
+ /// Most instructions that operate on vector arguments require vector
+ /// memory operands to be fully aligned (16-byte alignment for PNaCl
+ /// vector types). The stack frame layout and call ABI ensure proper
+ /// alignment for stack operands, but memory operands (originating
+ /// from load/store bitcode instructions) only have element-size
+ /// alignment guarantees. This function validates that none of the
+ /// operands is a memory operand of vector type, calling
+ /// report_fatal_error() if one is found. This function should be
+ /// called during emission, and maybe also in the ctor (as long as
+ /// that fits the lowering style).
void validateVectorAddrMode() const {
if (getDest())
validateVectorAddrModeOpnd(getDest());
@@ -328,12 +329,12 @@
}
};
-// InstX8632FakeRMW represents a non-atomic read-modify-write operation on a
-// memory location. An InstX8632FakeRMW is a "fake" instruction in that it
-// still needs to be lowered to some actual RMW instruction.
-//
-// If A is some memory address, D is some data value to apply, and OP is an
-// arithmetic operator, the instruction operates as: (*A) = (*A) OP D
+/// InstX8632FakeRMW represents a non-atomic read-modify-write operation on a
+/// memory location. An InstX8632FakeRMW is a "fake" instruction in that it
+/// still needs to be lowered to some actual RMW instruction.
+///
+/// If A is some memory address, D is some data value to apply, and OP is an
+/// arithmetic operator, the instruction operates as: (*A) = (*A) OP D
class InstX8632FakeRMW : public InstX8632 {
InstX8632FakeRMW() = delete;
InstX8632FakeRMW(const InstX8632FakeRMW &) = delete;
@@ -361,44 +362,44 @@
InstArithmetic::OpKind Op, Variable *Beacon);
};
-// InstX8632Label represents an intra-block label that is the target
-// of an intra-block branch. The offset between the label and the
-// branch must be fit into one byte (considered "near"). These are
-// used for lowering i1 calculations, Select instructions, and 64-bit
-// compares on a 32-bit architecture, without basic block splitting.
-// Basic block splitting is not so desirable for several reasons, one
-// of which is the impact on decisions based on whether a variable's
-// live range spans multiple basic blocks.
-//
-// Intra-block control flow must be used with caution. Consider the
-// sequence for "c = (a >= b ? x : y)".
-// cmp a, b
-// br lt, L1
-// mov c, x
-// jmp L2
-// L1:
-// mov c, y
-// L2:
-//
-// Labels L1 and L2 are intra-block labels. Without knowledge of the
-// intra-block control flow, liveness analysis will determine the "mov
-// c, x" instruction to be dead. One way to prevent this is to insert
-// a "FakeUse(c)" instruction anywhere between the two "mov c, ..."
-// instructions, e.g.:
-//
-// cmp a, b
-// br lt, L1
-// mov c, x
-// jmp L2
-// FakeUse(c)
-// L1:
-// mov c, y
-// L2:
-//
-// The down-side is that "mov c, x" can never be dead-code eliminated
-// even if there are no uses of c. As unlikely as this situation is,
-// it may be prevented by running dead code elimination before
-// lowering.
+/// InstX8632Label represents an intra-block label that is the target
+/// of an intra-block branch. The offset between the label and the
+/// branch must be fit into one byte (considered "near"). These are
+/// used for lowering i1 calculations, Select instructions, and 64-bit
+/// compares on a 32-bit architecture, without basic block splitting.
+/// Basic block splitting is not so desirable for several reasons, one
+/// of which is the impact on decisions based on whether a variable's
+/// live range spans multiple basic blocks.
+///
+/// Intra-block control flow must be used with caution. Consider the
+/// sequence for "c = (a >= b ? x : y)".
+/// cmp a, b
+/// br lt, L1
+/// mov c, x
+/// jmp L2
+/// L1:
+/// mov c, y
+/// L2:
+///
+/// Labels L1 and L2 are intra-block labels. Without knowledge of the
+/// intra-block control flow, liveness analysis will determine the "mov
+/// c, x" instruction to be dead. One way to prevent this is to insert
+/// a "FakeUse(c)" instruction anywhere between the two "mov c, ..."
+/// instructions, e.g.:
+///
+/// cmp a, b
+/// br lt, L1
+/// mov c, x
+/// jmp L2
+/// FakeUse(c)
+/// L1:
+/// mov c, y
+/// L2:
+///
+/// The down-side is that "mov c, x" can never be dead-code eliminated
+/// even if there are no uses of c. As unlikely as this situation is,
+/// it may be prevented by running dead code elimination before
+/// lowering.
class InstX8632Label : public InstX8632 {
InstX8632Label() = delete;
InstX8632Label(const InstX8632Label &) = delete;
@@ -418,17 +419,17 @@
private:
InstX8632Label(Cfg *Func, TargetX8632 *Target);
- SizeT Number; // used for unique label generation.
+ SizeT Number; /// used for unique label generation.
};
-// Conditional and unconditional branch instruction.
+/// Conditional and unconditional branch instruction.
class InstX8632Br : public InstX8632 {
InstX8632Br() = delete;
InstX8632Br(const InstX8632Br &) = delete;
InstX8632Br &operator=(const InstX8632Br &) = delete;
public:
- // Create a conditional branch to a node.
+ /// Create a conditional branch to a node.
static InstX8632Br *create(Cfg *Func, CfgNode *TargetTrue,
CfgNode *TargetFalse,
X8632::Traits::Cond::BrCond Condition) {
@@ -437,16 +438,16 @@
return new (Func->allocate<InstX8632Br>())
InstX8632Br(Func, TargetTrue, TargetFalse, NoLabel, Condition);
}
- // Create an unconditional branch to a node.
+ /// Create an unconditional branch to a node.
static InstX8632Br *create(Cfg *Func, CfgNode *Target) {
const CfgNode *NoCondTarget = nullptr;
const InstX8632Label *NoLabel = nullptr;
return new (Func->allocate<InstX8632Br>()) InstX8632Br(
Func, NoCondTarget, Target, NoLabel, X8632::Traits::Cond::Br_None);
}
- // Create a non-terminator conditional branch to a node, with a
- // fallthrough to the next instruction in the current node. This is
- // used for switch lowering.
+ /// Create a non-terminator conditional branch to a node, with a
+ /// fallthrough to the next instruction in the current node. This is
+ /// used for switch lowering.
static InstX8632Br *create(Cfg *Func, CfgNode *Target,
X8632::Traits::Cond::BrCond Condition) {
assert(Condition != X8632::Traits::Cond::Br_None);
@@ -455,8 +456,8 @@
return new (Func->allocate<InstX8632Br>())
InstX8632Br(Func, Target, NoUncondTarget, NoLabel, Condition);
}
- // Create a conditional intra-block branch (or unconditional, if
- // Condition==Br_None) to a label in the current block.
+ /// Create a conditional intra-block branch (or unconditional, if
+ /// Condition==Br_None) to a label in the current block.
static InstX8632Br *create(Cfg *Func, InstX8632Label *Label,
X8632::Traits::Cond::BrCond Condition) {
const CfgNode *NoCondTarget = nullptr;
@@ -494,12 +495,12 @@
X8632::Traits::Cond::BrCond Condition;
const CfgNode *TargetTrue;
const CfgNode *TargetFalse;
- const InstX8632Label *Label; // Intra-block branch target
+ const InstX8632Label *Label; /// Intra-block branch target
};
-// Jump to a target outside this function, such as tailcall, nacljump,
-// naclret, unreachable. This is different from a Branch instruction
-// in that there is no intra-function control flow to represent.
+/// Jump to a target outside this function, such as tailcall, nacljump,
+/// naclret, unreachable. This is different from a Branch instruction
+/// in that there is no intra-function control flow to represent.
class InstX8632Jmp : public InstX8632 {
InstX8632Jmp() = delete;
InstX8632Jmp(const InstX8632Jmp &) = delete;
@@ -519,8 +520,8 @@
InstX8632Jmp(Cfg *Func, Operand *Target);
};
-// AdjustStack instruction - subtracts esp by the given amount and
-// updates the stack offset during code emission.
+/// AdjustStack instruction - subtracts esp by the given amount and
+/// updates the stack offset during code emission.
class InstX8632AdjustStack : public InstX8632 {
InstX8632AdjustStack() = delete;
InstX8632AdjustStack(const InstX8632AdjustStack &) = delete;
@@ -541,7 +542,7 @@
SizeT Amount;
};
-// Call instruction. Arguments should have already been pushed.
+/// Call instruction. Arguments should have already been pushed.
class InstX8632Call : public InstX8632 {
InstX8632Call() = delete;
InstX8632Call(const InstX8632Call &) = delete;
@@ -562,14 +563,14 @@
InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget);
};
-// Emit a one-operand (GPR) instruction.
+/// Emit a one-operand (GPR) instruction.
void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Var,
const X8632::AssemblerX8632::GPREmitterOneOp &Emitter);
void emitIASAsAddrOpTyGPR(
const Cfg *Func, Type Ty, const Operand *Op0, const Operand *Op1,
const X8632::AssemblerX8632::GPREmitterAddrOp &Emitter);
-// Instructions of the form x := op(x).
+/// Instructions of the form x := op(x).
template <InstX8632::InstKindX8632 K>
class InstX8632InplaceopGPR : public InstX8632 {
InstX8632InplaceopGPR() = delete;
@@ -615,14 +616,14 @@
static const X8632::AssemblerX8632::GPREmitterOneOp Emitter;
};
-// Emit a two-operand (GPR) instruction, where the dest operand is a
-// Variable that's guaranteed to be a register.
+/// Emit a two-operand (GPR) instruction, where the dest operand is a
+/// Variable that's guaranteed to be a register.
template <bool VarCanBeByte = true, bool SrcCanBeByte = true>
void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Dst,
const Operand *Src,
const X8632::AssemblerX8632::GPREmitterRegOp &Emitter);
-// Instructions of the form x := op(y).
+/// Instructions of the form x := op(y).
template <InstX8632::InstKindX8632 K>
class InstX8632UnaryopGPR : public InstX8632 {
InstX8632UnaryopGPR() = delete;
@@ -736,7 +737,7 @@
InstX8632BinopGPRShift &operator=(const InstX8632BinopGPRShift &) = delete;
public:
- // Create a binary-op GPR shift instruction.
+ /// Create a binary-op GPR shift instruction.
static InstX8632BinopGPRShift *create(Cfg *Func, Variable *Dest,
Operand *Source) {
return new (Func->allocate<InstX8632BinopGPRShift>())
@@ -781,7 +782,7 @@
InstX8632BinopGPR &operator=(const InstX8632BinopGPR &) = delete;
public:
- // Create an ordinary binary-op instruction like add or sub.
+ /// Create an ordinary binary-op instruction like add or sub.
static InstX8632BinopGPR *create(Cfg *Func, Variable *Dest, Operand *Source) {
return new (Func->allocate<InstX8632BinopGPR>())
InstX8632BinopGPR(Func, Dest, Source);
@@ -825,7 +826,7 @@
InstX8632BinopRMW &operator=(const InstX8632BinopRMW &) = delete;
public:
- // Create an ordinary binary-op instruction like add or sub.
+ /// Create an ordinary binary-op instruction like add or sub.
static InstX8632BinopRMW *create(Cfg *Func, OperandX8632Mem *DestSrc0,
Operand *Src1) {
return new (Func->allocate<InstX8632BinopRMW>())
@@ -868,7 +869,7 @@
InstX8632BinopXmm &operator=(const InstX8632BinopXmm &) = delete;
public:
- // Create an XMM binary-op instruction like addss or addps.
+ /// Create an XMM binary-op instruction like addss or addps.
static InstX8632BinopXmm *create(Cfg *Func, Variable *Dest, Operand *Source) {
return new (Func->allocate<InstX8632BinopXmm>())
InstX8632BinopXmm(Func, Dest, Source);
@@ -920,7 +921,7 @@
InstX8632BinopXmmShift &operator=(const InstX8632BinopXmmShift &) = delete;
public:
- // Create an XMM binary-op shift operation.
+ /// Create an XMM binary-op shift operation.
static InstX8632BinopXmmShift *create(Cfg *Func, Variable *Dest,
Operand *Source) {
return new (Func->allocate<InstX8632BinopXmmShift>())
@@ -968,7 +969,7 @@
InstX8632Ternop &operator=(const InstX8632Ternop &) = delete;
public:
- // Create a ternary-op instruction like div or idiv.
+ /// Create a ternary-op instruction like div or idiv.
static InstX8632Ternop *create(Cfg *Func, Variable *Dest, Operand *Source1,
Operand *Source2) {
return new (Func->allocate<InstX8632Ternop>())
@@ -1008,7 +1009,7 @@
static const char *Opcode;
};
-// Instructions of the form x := y op z
+/// Instructions of the form x := y op z
template <InstX8632::InstKindX8632 K>
class InstX8632ThreeAddressop : public InstX8632 {
InstX8632ThreeAddressop() = delete;
@@ -1055,7 +1056,7 @@
static const char *Opcode;
};
-// Base class for assignment instructions
+/// Base class for assignment instructions
template <InstX8632::InstKindX8632 K>
class InstX8632Movlike : public InstX8632 {
InstX8632Movlike() = delete;
@@ -1098,18 +1099,18 @@
typedef InstX8632UnaryopGPR<InstX8632::Bsf> InstX8632Bsf;
typedef InstX8632UnaryopGPR<InstX8632::Bsr> InstX8632Bsr;
typedef InstX8632UnaryopGPR<InstX8632::Lea> InstX8632Lea;
-// Cbwdq instruction - wrapper for cbw, cwd, and cdq
+/// Cbwdq instruction - wrapper for cbw, cwd, and cdq
typedef InstX8632UnaryopGPR<InstX8632::Cbwdq> InstX8632Cbwdq;
typedef InstX8632UnaryopGPR<InstX8632::Movsx> InstX8632Movsx;
typedef InstX8632UnaryopGPR<InstX8632::Movzx> InstX8632Movzx;
typedef InstX8632UnaryopXmm<InstX8632::Movd> InstX8632Movd;
typedef InstX8632UnaryopXmm<InstX8632::Sqrtss> InstX8632Sqrtss;
-// Move/assignment instruction - wrapper for mov/movss/movsd.
+/// Move/assignment instruction - wrapper for mov/movss/movsd.
typedef InstX8632Movlike<InstX8632::Mov> InstX8632Mov;
-// Move packed - copy 128 bit values between XMM registers, or mem128
-// and XMM registers.
+/// Move packed - copy 128 bit values between XMM registers, or mem128
+/// and XMM registers.
typedef InstX8632Movlike<InstX8632::Movp> InstX8632Movp;
-// Movq - copy between XMM registers, or mem64 and XMM registers.
+/// Movq - copy between XMM registers, or mem64 and XMM registers.
typedef InstX8632Movlike<InstX8632::Movq> InstX8632Movq;
typedef InstX8632BinopGPR<InstX8632::Add> InstX8632Add;
typedef InstX8632BinopRMW<InstX8632::AddRMW> InstX8632AddRMW;
@@ -1151,13 +1152,13 @@
typedef InstX8632BinopXmmShift<InstX8632::Psra> InstX8632Psra;
typedef InstX8632BinopXmm<InstX8632::Pcmpeq, true> InstX8632Pcmpeq;
typedef InstX8632BinopXmm<InstX8632::Pcmpgt, true> InstX8632Pcmpgt;
-// movss is only a binary operation when the source and dest
-// operands are both registers (the high bits of dest are left untouched).
-// In other cases, it behaves like a copy (mov-like) operation (and the
-// high bits of dest are cleared).
-// InstX8632Movss will assert that both its source and dest operands are
-// registers, so the lowering code should use _mov instead of _movss
-// in cases where a copy operation is intended.
+/// movss is only a binary operation when the source and dest
+/// operands are both registers (the high bits of dest are left untouched).
+/// In other cases, it behaves like a copy (mov-like) operation (and the
+/// high bits of dest are cleared).
+/// InstX8632Movss will assert that both its source and dest operands are
+/// registers, so the lowering code should use _mov instead of _movss
+/// in cases where a copy operation is intended.
typedef InstX8632BinopXmm<InstX8632::MovssRegs, false> InstX8632MovssRegs;
typedef InstX8632Ternop<InstX8632::Idiv> InstX8632Idiv;
typedef InstX8632Ternop<InstX8632::Div> InstX8632Div;
@@ -1169,7 +1170,7 @@
typedef InstX8632ThreeAddressop<InstX8632::Pextr> InstX8632Pextr;
typedef InstX8632ThreeAddressop<InstX8632::Pshufd> InstX8632Pshufd;
-// Base class for a lockable x86-32 instruction (emits a locked prefix).
+/// Base class for a lockable x86-32 instruction (emits a locked prefix).
class InstX8632Lockable : public InstX8632 {
InstX8632Lockable() = delete;
InstX8632Lockable(const InstX8632Lockable &) = delete;
@@ -1187,7 +1188,7 @@
}
};
-// Mul instruction - unsigned multiply.
+/// Mul instruction - unsigned multiply.
class InstX8632Mul : public InstX8632 {
InstX8632Mul() = delete;
InstX8632Mul(const InstX8632Mul &) = delete;
@@ -1208,7 +1209,7 @@
InstX8632Mul(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2);
};
-// Shld instruction - shift across a pair of operands.
+/// Shld instruction - shift across a pair of operands.
class InstX8632Shld : public InstX8632 {
InstX8632Shld() = delete;
InstX8632Shld(const InstX8632Shld &) = delete;
@@ -1230,7 +1231,7 @@
Variable *Source2);
};
-// Shrd instruction - shift across a pair of operands.
+/// Shrd instruction - shift across a pair of operands.
class InstX8632Shrd : public InstX8632 {
InstX8632Shrd() = delete;
InstX8632Shrd(const InstX8632Shrd &) = delete;
@@ -1252,7 +1253,7 @@
Variable *Source2);
};
-// Conditional move instruction.
+/// Conditional move instruction.
class InstX8632Cmov : public InstX8632 {
InstX8632Cmov() = delete;
InstX8632Cmov(const InstX8632Cmov &) = delete;
@@ -1276,8 +1277,8 @@
X8632::Traits::Cond::BrCond Condition;
};
-// Cmpps instruction - compare packed singled-precision floating point
-// values
+/// Cmpps instruction - compare packed singled-precision floating point
+/// values
class InstX8632Cmpps : public InstX8632 {
InstX8632Cmpps() = delete;
InstX8632Cmpps(const InstX8632Cmpps &) = delete;
@@ -1301,11 +1302,11 @@
X8632::Traits::Cond::CmppsCond Condition;
};
-// Cmpxchg instruction - cmpxchg <dest>, <desired> will compare if <dest>
-// equals eax. If so, the ZF is set and <desired> is stored in <dest>.
-// If not, ZF is cleared and <dest> is copied to eax (or subregister).
-// <dest> can be a register or memory, while <desired> must be a register.
-// It is the user's responsiblity to mark eax with a FakeDef.
+/// Cmpxchg instruction - cmpxchg <dest>, <desired> will compare if <dest>
+/// equals eax. If so, the ZF is set and <desired> is stored in <dest>.
+/// If not, ZF is cleared and <dest> is copied to eax (or subregister).
+/// <dest> can be a register or memory, while <desired> must be a register.
+/// It is the user's responsiblity to mark eax with a FakeDef.
class InstX8632Cmpxchg : public InstX8632Lockable {
InstX8632Cmpxchg() = delete;
InstX8632Cmpxchg(const InstX8632Cmpxchg &) = delete;
@@ -1327,12 +1328,12 @@
Variable *Desired, bool Locked);
};
-// Cmpxchg8b instruction - cmpxchg8b <m64> will compare if <m64>
-// equals edx:eax. If so, the ZF is set and ecx:ebx is stored in <m64>.
-// If not, ZF is cleared and <m64> is copied to edx:eax.
-// The caller is responsible for inserting FakeDefs to mark edx
-// and eax as modified.
-// <m64> must be a memory operand.
+/// Cmpxchg8b instruction - cmpxchg8b <m64> will compare if <m64>
+/// equals edx:eax. If so, the ZF is set and ecx:ebx is stored in <m64>.
+/// If not, ZF is cleared and <m64> is copied to edx:eax.
+/// The caller is responsible for inserting FakeDefs to mark edx
+/// and eax as modified.
+/// <m64> must be a memory operand.
class InstX8632Cmpxchg8b : public InstX8632Lockable {
InstX8632Cmpxchg8b() = delete;
InstX8632Cmpxchg8b(const InstX8632Cmpxchg8b &) = delete;
@@ -1355,10 +1356,10 @@
Variable *Eax, Variable *Ecx, Variable *Ebx, bool Locked);
};
-// Cvt instruction - wrapper for cvtsX2sY where X and Y are in {s,d,i}
-// as appropriate. s=float, d=double, i=int. X and Y are determined
-// from dest/src types. Sign and zero extension on the integer
-// operand needs to be done separately.
+/// Cvt instruction - wrapper for cvtsX2sY where X and Y are in {s,d,i}
+/// as appropriate. s=float, d=double, i=int. X and Y are determined
+/// from dest/src types. Sign and zero extension on the integer
+/// operand needs to be done separately.
class InstX8632Cvt : public InstX8632 {
InstX8632Cvt() = delete;
InstX8632Cvt(const InstX8632Cvt &) = delete;
@@ -1382,7 +1383,7 @@
InstX8632Cvt(Cfg *Func, Variable *Dest, Operand *Source, CvtVariant Variant);
};
-// cmp - Integer compare instruction.
+/// cmp - Integer compare instruction.
class InstX8632Icmp : public InstX8632 {
InstX8632Icmp() = delete;
InstX8632Icmp(const InstX8632Icmp &) = delete;
@@ -1402,7 +1403,7 @@
InstX8632Icmp(Cfg *Func, Operand *Src1, Operand *Src2);
};
-// ucomiss/ucomisd - floating-point compare instruction.
+/// ucomiss/ucomisd - floating-point compare instruction.
class InstX8632Ucomiss : public InstX8632 {
InstX8632Ucomiss() = delete;
InstX8632Ucomiss(const InstX8632Ucomiss &) = delete;
@@ -1422,7 +1423,7 @@
InstX8632Ucomiss(Cfg *Func, Operand *Src1, Operand *Src2);
};
-// UD2 instruction.
+/// UD2 instruction.
class InstX8632UD2 : public InstX8632 {
InstX8632UD2() = delete;
InstX8632UD2(const InstX8632UD2 &) = delete;
@@ -1441,7 +1442,7 @@
explicit InstX8632UD2(Cfg *Func);
};
-// Test instruction.
+/// Test instruction.
class InstX8632Test : public InstX8632 {
InstX8632Test() = delete;
InstX8632Test(const InstX8632Test &) = delete;
@@ -1461,7 +1462,7 @@
InstX8632Test(Cfg *Func, Operand *Source1, Operand *Source2);
};
-// Mfence instruction.
+/// Mfence instruction.
class InstX8632Mfence : public InstX8632 {
InstX8632Mfence() = delete;
InstX8632Mfence(const InstX8632Mfence &) = delete;
@@ -1480,9 +1481,9 @@
explicit InstX8632Mfence(Cfg *Func);
};
-// This is essentially a "mov" instruction with an OperandX8632Mem
-// operand instead of Variable as the destination. It's important
-// for liveness that there is no Dest operand.
+/// This is essentially a "mov" instruction with an OperandX8632Mem
+/// operand instead of Variable as the destination. It's important
+/// for liveness that there is no Dest operand.
class InstX8632Store : public InstX8632 {
InstX8632Store() = delete;
InstX8632Store(const InstX8632Store &) = delete;
@@ -1502,10 +1503,10 @@
InstX8632Store(Cfg *Func, Operand *Value, OperandX8632 *Mem);
};
-// This is essentially a vector "mov" instruction with an OperandX8632Mem
-// operand instead of Variable as the destination. It's important
-// for liveness that there is no Dest operand. The source must be an
-// Xmm register, since Dest is mem.
+/// This is essentially a vector "mov" instruction with an OperandX8632Mem
+/// operand instead of Variable as the destination. It's important
+/// for liveness that there is no Dest operand. The source must be an
+/// Xmm register, since Dest is mem.
class InstX8632StoreP : public InstX8632 {
InstX8632StoreP() = delete;
InstX8632StoreP(const InstX8632StoreP &) = delete;
@@ -1546,7 +1547,7 @@
InstX8632StoreQ(Cfg *Func, Variable *Value, OperandX8632Mem *Mem);
};
-// Nop instructions of varying length
+/// Nop instructions of varying length
class InstX8632Nop : public InstX8632 {
InstX8632Nop() = delete;
InstX8632Nop(const InstX8632Nop &) = delete;
@@ -1570,7 +1571,7 @@
NopVariant Variant;
};
-// Fld - load a value onto the x87 FP stack.
+/// Fld - load a value onto the x87 FP stack.
class InstX8632Fld : public InstX8632 {
InstX8632Fld() = delete;
InstX8632Fld(const InstX8632Fld &) = delete;
@@ -1589,7 +1590,7 @@
InstX8632Fld(Cfg *Func, Operand *Src);
};
-// Fstp - store x87 st(0) into memory and pop st(0).
+/// Fstp - store x87 st(0) into memory and pop st(0).
class InstX8632Fstp : public InstX8632 {
InstX8632Fstp() = delete;
InstX8632Fstp(const InstX8632Fstp &) = delete;
@@ -1644,10 +1645,10 @@
InstX8632Push(Cfg *Func, Variable *Source);
};
-// Ret instruction. Currently only supports the "ret" version that
-// does not pop arguments. This instruction takes a Source operand
-// (for non-void returning functions) for liveness analysis, though
-// a FakeUse before the ret would do just as well.
+/// Ret instruction. Currently only supports the "ret" version that
+/// does not pop arguments. This instruction takes a Source operand
+/// (for non-void returning functions) for liveness analysis, though
+/// a FakeUse before the ret would do just as well.
class InstX8632Ret : public InstX8632 {
InstX8632Ret() = delete;
InstX8632Ret(const InstX8632Ret &) = delete;
@@ -1666,7 +1667,7 @@
InstX8632Ret(Cfg *Func, Variable *Source);
};
-// Conditional set-byte instruction.
+/// Conditional set-byte instruction.
class InstX8632Setcc : public InstX8632 {
InstX8632Setcc() = delete;
InstX8632Setcc(const InstX8632Cmov &) = delete;
@@ -1689,13 +1690,13 @@
const X8632::Traits::Cond::BrCond Condition;
};
-// Exchanging Add instruction. Exchanges the first operand (destination
-// operand) with the second operand (source operand), then loads the sum
-// of the two values into the destination operand. The destination may be
-// a register or memory, while the source must be a register.
-//
-// Both the dest and source are updated. The caller should then insert a
-// FakeDef to reflect the second udpate.
+/// Exchanging Add instruction. Exchanges the first operand (destination
+/// operand) with the second operand (source operand), then loads the sum
+/// of the two values into the destination operand. The destination may be
+/// a register or memory, while the source must be a register.
+///
+/// Both the dest and source are updated. The caller should then insert a
+/// FakeDef to reflect the second udpate.
class InstX8632Xadd : public InstX8632Lockable {
InstX8632Xadd() = delete;
InstX8632Xadd(const InstX8632Xadd &) = delete;
@@ -1716,12 +1717,12 @@
InstX8632Xadd(Cfg *Func, Operand *Dest, Variable *Source, bool Locked);
};
-// Exchange instruction. Exchanges the first operand (destination
-// operand) with the second operand (source operand). At least one of
-// the operands must be a register (and the other can be reg or mem).
-// Both the Dest and Source are updated. If there is a memory operand,
-// then the instruction is automatically "locked" without the need for
-// a lock prefix.
+/// Exchange instruction. Exchanges the first operand (destination
+/// operand) with the second operand (source operand). At least one of
+/// the operands must be a register (and the other can be reg or mem).
+/// Both the Dest and Source are updated. If there is a memory operand,
+/// then the instruction is automatically "locked" without the need for
+/// a lock prefix.
class InstX8632Xchg : public InstX8632 {
InstX8632Xchg() = delete;
InstX8632Xchg(const InstX8632Xchg &) = delete;
@@ -1741,9 +1742,9 @@
InstX8632Xchg(Cfg *Func, Operand *Dest, Variable *Source);
};
-// Declare partial template specializations of emit() methods that
-// already have default implementations. Without this, there is the
-// possibility of ODR violations and link errors.
+/// Declare partial template specializations of emit() methods that
+/// already have default implementations. Without this, there is the
+/// possibility of ODR violations and link errors.
template <> void InstX8632Addss::emit(const Cfg *Func) const;
template <> void InstX8632Blendvps::emit(const Cfg *Func) const;
template <> void InstX8632Cbwdq::emit(const Cfg *Func) const;
diff --git a/src/IceIntrinsics.cpp b/src/IceIntrinsics.cpp
index 307745e..b1ca40d 100644
--- a/src/IceIntrinsics.cpp
+++ b/src/IceIntrinsics.cpp
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the Intrinsics utilities for matching and
-// then dispatching by name.
-//
+///
+/// \file
+/// This file implements the Intrinsics utilities for matching and
+/// then dispatching by name.
+///
//===----------------------------------------------------------------------===//
#include "IceIntrinsics.h"
diff --git a/src/IceIntrinsics.h b/src/IceIntrinsics.h
index 938243f..674c9ab 100644
--- a/src/IceIntrinsics.h
+++ b/src/IceIntrinsics.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the kinds of intrinsics supported by PNaCl.
-//
+///
+/// \file
+/// This file declares the kinds of intrinsics supported by PNaCl.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEINTRINSICS_H
@@ -31,9 +32,9 @@
Intrinsics();
~Intrinsics();
- // Some intrinsics allow overloading by type. This enum collapses all
- // overloads into a single ID, but the type can still be recovered by the
- // type of the intrinsic function call's return value and parameters.
+ /// Some intrinsics allow overloading by type. This enum collapses all
+ /// overloads into a single ID, but the type can still be recovered by the
+ /// type of the intrinsic function call's return value and parameters.
enum IntrinsicID {
UnknownIntrinsic = 0,
// Arbitrary (alphabetical) order.
@@ -92,9 +93,9 @@
MemoryOrderNum // Invalid, keep last.
};
- // Verify memory ordering rules for atomic intrinsics. For
- // AtomicCmpxchg, Order is the "success" ordering and OrderOther is
- // the "failure" ordering. Returns true if valid, false if invalid.
+ /// Verify memory ordering rules for atomic intrinsics. For
+ /// AtomicCmpxchg, Order is the "success" ordering and OrderOther is
+ /// the "failure" ordering. Returns true if valid, false if invalid.
// TODO(stichnot,kschimpf): Perform memory order validation in the
// bitcode reader/parser, allowing LLVM and Subzero to share. See
// https://code.google.com/p/nativeclient/issues/detail?id=4126 .
@@ -105,61 +106,61 @@
enum ReturnsTwice { ReturnsTwice_F = 0, ReturnsTwice_T = 1 };
- // Basic attributes related to each intrinsic, that are relevant to
- // code generation. Perhaps the attributes representation can be shared
- // with general function calls, but PNaCl currently strips all
- // attributes from functions.
+ /// Basic attributes related to each intrinsic, that are relevant to
+ /// code generation. Perhaps the attributes representation can be shared
+ /// with general function calls, but PNaCl currently strips all
+ /// attributes from functions.
struct IntrinsicInfo {
enum IntrinsicID ID : 30;
enum SideEffects HasSideEffects : 1;
enum ReturnsTwice ReturnsTwice : 1;
};
- // The types of validation values for FullIntrinsicInfo.validateCall.
+ /// The types of validation values for FullIntrinsicInfo.validateCall.
enum ValidateCallValue {
- IsValidCall, // Valid use of instrinsic call.
- BadReturnType, // Return type invalid for intrinsic.
- WrongNumOfArgs, // Wrong number of arguments for intrinsic.
- WrongCallArgType, // Argument of wrong type.
+ IsValidCall, /// Valid use of instrinsic call.
+ BadReturnType, /// Return type invalid for intrinsic.
+ WrongNumOfArgs, /// Wrong number of arguments for intrinsic.
+ WrongCallArgType, /// Argument of wrong type.
};
- // The complete set of information about an intrinsic.
+ /// The complete set of information about an intrinsic.
struct FullIntrinsicInfo {
- struct IntrinsicInfo Info; // Information that CodeGen would care about.
+ struct IntrinsicInfo Info; /// Information that CodeGen would care about.
// Sanity check during parsing.
Type Signature[kMaxIntrinsicParameters];
uint8_t NumTypes;
- // Validates that type signature of call matches intrinsic.
- // If WrongArgumentType is returned, ArgIndex is set to corresponding
- // argument index.
+ /// Validates that type signature of call matches intrinsic.
+ /// If WrongArgumentType is returned, ArgIndex is set to corresponding
+ /// argument index.
ValidateCallValue validateCall(const Ice::InstCall *Call,
SizeT &ArgIndex) const;
- // Returns the return type of the intrinsic.
+ /// Returns the return type of the intrinsic.
Type getReturnType() const {
assert(NumTypes > 1);
return Signature[0];
}
- // Returns number of arguments expected.
+ /// Returns number of arguments expected.
SizeT getNumArgs() const {
assert(NumTypes > 1);
return NumTypes - 1;
}
- // Returns type of Index-th argument.
+ /// Returns type of Index-th argument.
Type getArgType(SizeT Index) const;
};
- // Find the information about a given intrinsic, based on function name. If
- // the function name does not have the common "llvm." prefix, nullptr is
- // returned and Error is set to false. Otherwise, tries to find a reference
- // to a FullIntrinsicInfo entry (valid for the lifetime of the map). If
- // found, sets Error to false and returns the reference. If not found, sets
- // Error to true and returns nullptr (indicating an unknown "llvm.foo"
- // intrinsic).
+ /// Find the information about a given intrinsic, based on function name. If
+ /// the function name does not have the common "llvm." prefix, nullptr is
+ /// returned and Error is set to false. Otherwise, tries to find a reference
+ /// to a FullIntrinsicInfo entry (valid for the lifetime of the map). If
+ /// found, sets Error to false and returns the reference. If not found, sets
+ /// Error to true and returns nullptr (indicating an unknown "llvm.foo"
+ /// intrinsic).
const FullIntrinsicInfo *find(const IceString &Name, bool &Error) const;
private:
diff --git a/src/IceLiveness.cpp b/src/IceLiveness.cpp
index f3c4516..551a400 100644
--- a/src/IceLiveness.cpp
+++ b/src/IceLiveness.cpp
@@ -6,17 +6,18 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file provides some of the support for the Liveness class. In
-// particular, it handles the sparsity representation of the mapping
-// between Variables and CfgNodes. The idea is that since most
-// variables are used only within a single basic block, we can
-// partition the variables into "local" and "global" sets. Instead of
-// sizing and indexing vectors according to Variable::Number, we
-// create a mapping such that global variables are mapped to low
-// indexes that are common across nodes, and local variables are
-// mapped to a higher index space that is shared across nodes.
-//
+///
+/// \file
+/// This file provides some of the support for the Liveness class. In
+/// particular, it handles the sparsity representation of the mapping
+/// between Variables and CfgNodes. The idea is that since most
+/// variables are used only within a single basic block, we can
+/// partition the variables into "local" and "global" sets. Instead of
+/// sizing and indexing vectors according to Variable::Number, we
+/// create a mapping such that global variables are mapped to low
+/// indexes that are common across nodes, and local variables are
+/// mapped to a higher index space that is shared across nodes.
+///
//===----------------------------------------------------------------------===//
#include "IceLiveness.h"
diff --git a/src/IceLiveness.h b/src/IceLiveness.h
index 03c63ad..7fcad25 100644
--- a/src/IceLiveness.h
+++ b/src/IceLiveness.h
@@ -6,15 +6,16 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the Liveness and LivenessNode classes,
-// which are used for liveness analysis. The node-specific
-// information tracked for each Variable includes whether it is
-// live on entry, whether it is live on exit, the instruction number
-// that starts its live range, and the instruction number that ends
-// its live range. At the Cfg level, the actual live intervals are
-// recorded.
-//
+///
+/// \file
+/// This file declares the Liveness and LivenessNode classes,
+/// which are used for liveness analysis. The node-specific
+/// information tracked for each Variable includes whether it is
+/// live on entry, whether it is live on exit, the instruction number
+/// that starts its live range, and the instruction number that ends
+/// its live range. At the Cfg level, the actual live intervals are
+/// recorded.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICELIVENESS_H
@@ -37,12 +38,12 @@
public:
LivenessNode() = default;
LivenessNode(const LivenessNode &) = default;
- // NumLocals is the number of Variables local to this block.
+ /// NumLocals is the number of Variables local to this block.
SizeT NumLocals = 0;
- // NumNonDeadPhis tracks the number of Phi instructions that
- // Inst::liveness() identified as tentatively live. If
- // NumNonDeadPhis changes from the last liveness pass, then liveness
- // has not yet converged.
+ /// NumNonDeadPhis tracks the number of Phi instructions that
+ /// Inst::liveness() identified as tentatively live. If
+ /// NumNonDeadPhis changes from the last liveness pass, then liveness
+ /// has not yet converged.
SizeT NumNonDeadPhis = 0;
// LiveToVarMap maps a liveness bitvector index to a Variable. This
// is generally just for printing/dumping. The index should be less
@@ -95,7 +96,7 @@
}
private:
- // Resize Nodes so that Nodes[Index] is valid.
+ /// Resize Nodes so that Nodes[Index] is valid.
void resize(SizeT Index) {
if (Index >= Nodes.size())
Nodes.resize(Index + 1);
@@ -103,13 +104,13 @@
Cfg *Func;
LivenessMode Mode;
SizeT NumGlobals = 0;
- // Size of Nodes is Cfg::Nodes.size().
+ /// Size of Nodes is Cfg::Nodes.size().
std::vector<LivenessNode> Nodes;
- // VarToLiveMap maps a Variable's Variable::Number to its live index
- // within its basic block.
+ /// VarToLiveMap maps a Variable's Variable::Number to its live index
+ /// within its basic block.
std::vector<SizeT> VarToLiveMap;
- // LiveToVarMap is analogous to LivenessNode::LiveToVarMap, but for
- // non-local variables.
+ /// LiveToVarMap is analogous to LivenessNode::LiveToVarMap, but for
+ /// non-local variables.
std::vector<Variable *> LiveToVarMap;
};
diff --git a/src/IceOperand.cpp b/src/IceOperand.cpp
index 60a73d9..0d739ca 100644
--- a/src/IceOperand.cpp
+++ b/src/IceOperand.cpp
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the Operand class and its target-independent
-// subclasses, primarily for the methods of the Variable class.
-//
+///
+/// \file
+/// This file implements the Operand class and its target-independent
+/// subclasses, primarily for the methods of the Variable class.
+///
//===----------------------------------------------------------------------===//
#include "IceOperand.h"
diff --git a/src/IceOperand.h b/src/IceOperand.h
index b43e2a8..8db3cf1 100644
--- a/src/IceOperand.h
+++ b/src/IceOperand.h
@@ -6,13 +6,14 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the Operand class and its target-independent
-// subclasses. The main classes are Variable, which represents an
-// LLVM variable that is either register- or stack-allocated, and the
-// Constant hierarchy, which represents integer, floating-point,
-// and/or symbolic constants.
-//
+///
+/// \file
+/// This file declares the Operand class and its target-independent
+/// subclasses. The main classes are Variable, which represents an
+/// LLVM variable that is either register- or stack-allocated, and the
+/// Constant hierarchy, which represents integer, floating-point,
+/// and/or symbolic constants.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEOPERAND_H
@@ -55,18 +56,22 @@
OperandKind getKind() const { return Kind; }
Type getType() const { return Ty; }
- // Every Operand keeps an array of the Variables referenced in
- // the operand. This is so that the liveness operations can get
- // quick access to the variables of interest, without having to dig
- // so far into the operand.
+ /// Every Operand keeps an array of the Variables referenced in
+ /// the operand. This is so that the liveness operations can get
+ /// quick access to the variables of interest, without having to dig
+ /// so far into the operand.
SizeT getNumVars() const { return NumVars; }
Variable *getVar(SizeT I) const {
assert(I < getNumVars());
return Vars[I];
}
virtual void emit(const Cfg *Func) const = 0;
- // The dump(Func,Str) implementation must be sure to handle the
- // situation where Func==nullptr.
+
+ /// \name Dumping functions.
+ /// @{
+
+ /// The dump(Func,Str) implementation must be sure to handle the
+ /// situation where Func==nullptr.
virtual void dump(const Cfg *Func, Ostream &Str) const = 0;
void dump(const Cfg *Func) const {
if (!BuildDefs::dump())
@@ -78,6 +83,7 @@
if (BuildDefs::dump())
dump(nullptr, Str);
}
+ /// @}
protected:
Operand(OperandKind Kind, Type Ty) : Ty(Ty), Kind(Kind) {}
@@ -85,7 +91,7 @@
const Type Ty;
const OperandKind Kind;
- // Vars and NumVars are initialized by the derived class.
+ /// Vars and NumVars are initialized by the derived class.
SizeT NumVars = 0;
Variable **Vars = nullptr;
};
@@ -96,8 +102,8 @@
return Str;
}
-// Constant is the abstract base class for constants. All
-// constants are allocated from a global arena and are pooled.
+/// Constant is the abstract base class for constants. All
+/// constants are allocated from a global arena and are pooled.
class Constant : public Operand {
Constant() = delete;
Constant(const Constant &) = delete;
@@ -115,9 +121,9 @@
return Kind >= kConst_Base && Kind <= kConst_Num;
}
- // Judge if this given immediate should be randomized or pooled
- // By default should return false, only constant integers should
- // truly go through this method.
+ /// Judge if this given immediate should be randomized or pooled
+ /// By default should return false, only constant integers should
+ /// truly go through this method.
virtual bool shouldBeRandomizedOrPooled(const GlobalContext *Ctx) {
(void)Ctx;
return false;
@@ -133,16 +139,16 @@
Vars = nullptr;
NumVars = 0;
}
- // PoolEntryID is an integer that uniquely identifies the constant
- // within its constant pool. It is used for building the constant
- // pool in the object code and for referencing its entries.
+ /// PoolEntryID is an integer that uniquely identifies the constant
+ /// within its constant pool. It is used for building the constant
+ /// pool in the object code and for referencing its entries.
const uint32_t PoolEntryID;
- // Whether we should pool this constant. Usually Float/Double and pooled
- // Integers should be flagged true.
+ /// Whether we should pool this constant. Usually Float/Double and pooled
+ /// Integers should be flagged true.
bool shouldBePooled;
};
-// ConstantPrimitive<> wraps a primitive type.
+/// ConstantPrimitive<> wraps a primitive type.
template <typename T, Operand::OperandKind K>
class ConstantPrimitive : public Constant {
ConstantPrimitive() = delete;
@@ -198,7 +204,7 @@
Str << static_cast<int32_t>(getValue());
}
-// Specialization of the template member function for ConstantInteger32
+/// Specialization of the template member function for ConstantInteger32
template <>
bool ConstantInteger32::shouldBeRandomizedOrPooled(const GlobalContext *Ctx);
@@ -210,10 +216,10 @@
Str << static_cast<int64_t>(getValue());
}
-// RelocatableTuple bundles the parameters that are used to
-// construct an ConstantRelocatable. It is done this way so that
-// ConstantRelocatable can fit into the global constant pool
-// template mechanism.
+/// RelocatableTuple bundles the parameters that are used to
+/// construct an ConstantRelocatable. It is done this way so that
+/// ConstantRelocatable can fit into the global constant pool
+/// template mechanism.
class RelocatableTuple {
RelocatableTuple() = delete;
RelocatableTuple &operator=(const RelocatableTuple &) = delete;
@@ -231,8 +237,8 @@
bool operator==(const RelocatableTuple &A, const RelocatableTuple &B);
-// ConstantRelocatable represents a symbolic constant combined with
-// a fixed offset.
+/// ConstantRelocatable represents a symbolic constant combined with
+/// a fixed offset.
class ConstantRelocatable : public Constant {
ConstantRelocatable() = delete;
ConstantRelocatable(const ConstantRelocatable &) = delete;
@@ -268,14 +274,14 @@
bool SuppressMangling, uint32_t PoolEntryID)
: Constant(kConstRelocatable, Ty, PoolEntryID), Offset(Offset),
Name(Name), SuppressMangling(SuppressMangling) {}
- const RelocOffsetT Offset; // fixed offset to add
- const IceString Name; // optional for debug/dump
+ const RelocOffsetT Offset; /// fixed offset to add
+ const IceString Name; /// optional for debug/dump
bool SuppressMangling;
};
-// ConstantUndef represents an unspecified bit pattern. Although it is
-// legal to lower ConstantUndef to any value, backends should try to
-// make code generation deterministic by lowering ConstantUndefs to 0.
+/// ConstantUndef represents an unspecified bit pattern. Although it is
+/// legal to lower ConstantUndef to any value, backends should try to
+/// make code generation deterministic by lowering ConstantUndefs to 0.
class ConstantUndef : public Constant {
ConstantUndef() = delete;
ConstantUndef(const ConstantUndef &) = delete;
@@ -306,17 +312,17 @@
: Constant(kConstUndef, Ty, PoolEntryID) {}
};
-// RegWeight is a wrapper for a uint32_t weight value, with a
-// special value that represents infinite weight, and an addWeight()
-// method that ensures that W+infinity=infinity.
+/// RegWeight is a wrapper for a uint32_t weight value, with a
+/// special value that represents infinite weight, and an addWeight()
+/// method that ensures that W+infinity=infinity.
class RegWeight {
public:
RegWeight() = default;
explicit RegWeight(uint32_t Weight) : Weight(Weight) {}
RegWeight(const RegWeight &) = default;
RegWeight &operator=(const RegWeight &) = default;
- const static uint32_t Inf = ~0; // Force regalloc to give a register
- const static uint32_t Zero = 0; // Force regalloc NOT to give a register
+ const static uint32_t Inf = ~0; /// Force regalloc to give a register
+ const static uint32_t Zero = 0; /// Force regalloc NOT to give a register
void addWeight(uint32_t Delta) {
if (Delta == Inf)
Weight = Inf;
@@ -337,17 +343,17 @@
bool operator<=(const RegWeight &A, const RegWeight &B);
bool operator==(const RegWeight &A, const RegWeight &B);
-// LiveRange is a set of instruction number intervals representing
-// a variable's live range. Generally there is one interval per basic
-// block where the variable is live, but adjacent intervals get
-// coalesced into a single interval. LiveRange also includes a
-// weight, in case e.g. we want a live range to have higher weight
-// inside a loop.
+/// LiveRange is a set of instruction number intervals representing
+/// a variable's live range. Generally there is one interval per basic
+/// block where the variable is live, but adjacent intervals get
+/// coalesced into a single interval. LiveRange also includes a
+/// weight, in case e.g. we want a live range to have higher weight
+/// inside a loop.
class LiveRange {
public:
LiveRange() = default;
- // Special constructor for building a kill set. The advantage is
- // that we can reserve the right amount of space in advance.
+ /// Special constructor for building a kill set. The advantage is
+ /// that we can reserve the right amount of space in advance.
explicit LiveRange(const std::vector<InstNumberT> &Kills) {
Range.reserve(Kills.size());
for (InstNumberT I : Kills)
@@ -382,27 +388,27 @@
private:
typedef std::pair<InstNumberT, InstNumberT> RangeElementType;
- // RangeType is arena-allocated from the Cfg's allocator.
+ /// RangeType is arena-allocated from the Cfg's allocator.
typedef std::vector<RangeElementType, CfgLocalAllocator<RangeElementType>>
RangeType;
RangeType Range;
RegWeight Weight = RegWeight(0);
- // TrimmedBegin is an optimization for the overlaps() computation.
- // Since the linear-scan algorithm always calls it as overlaps(Cur)
- // and Cur advances monotonically according to live range start, we
- // can optimize overlaps() by ignoring all segments that end before
- // the start of Cur's range. The linear-scan code enables this by
- // calling trim() on the ranges of interest as Cur advances. Note
- // that linear-scan also has to initialize TrimmedBegin at the
- // beginning by calling untrim().
+ /// TrimmedBegin is an optimization for the overlaps() computation.
+ /// Since the linear-scan algorithm always calls it as overlaps(Cur)
+ /// and Cur advances monotonically according to live range start, we
+ /// can optimize overlaps() by ignoring all segments that end before
+ /// the start of Cur's range. The linear-scan code enables this by
+ /// calling trim() on the ranges of interest as Cur advances. Note
+ /// that linear-scan also has to initialize TrimmedBegin at the
+ /// beginning by calling untrim().
RangeType::const_iterator TrimmedBegin;
};
Ostream &operator<<(Ostream &Str, const LiveRange &L);
-// Variable represents an operand that is register-allocated or
-// stack-allocated. If it is register-allocated, it will ultimately
-// have a non-negative RegNum field.
+/// Variable represents an operand that is register-allocated or
+/// stack-allocated. If it is register-allocated, it will ultimately
+/// have a non-negative RegNum field.
class Variable : public Operand {
Variable() = delete;
Variable(const Variable &) = delete;
@@ -486,11 +492,11 @@
LoVar = Lo;
HiVar = Hi;
}
- // Creates a temporary copy of the variable with a different type.
- // Used primarily for syntactic correctness of textual assembly
- // emission. Note that only basic information is copied, in
- // particular not IsArgument, IsImplicitArgument, IgnoreLiveness,
- // RegNumTmp, Weight, Live, LoVar, HiVar, VarsReal.
+ /// Creates a temporary copy of the variable with a different type.
+ /// Used primarily for syntactic correctness of textual assembly
+ /// emission. Note that only basic information is copied, in
+ /// particular not IsArgument, IsImplicitArgument, IgnoreLiveness,
+ /// RegNumTmp, Weight, Live, LoVar, HiVar, VarsReal.
Variable *asType(Type Ty);
void emit(const Cfg *Func) const override;
@@ -509,23 +515,23 @@
Vars[0] = this;
NumVars = 1;
}
- // Number is unique across all variables, and is used as a
- // (bit)vector index for liveness analysis.
+ /// Number is unique across all variables, and is used as a
+ /// (bit)vector index for liveness analysis.
const SizeT Number;
Cfg::IdentifierIndexType NameIndex = Cfg::IdentifierIndexInvalid;
bool IsArgument = false;
bool IsImplicitArgument = false;
- // IgnoreLiveness means that the variable should be ignored when
- // constructing and validating live ranges. This is usually
- // reserved for the stack pointer.
+ /// IgnoreLiveness means that the variable should be ignored when
+ /// constructing and validating live ranges. This is usually
+ /// reserved for the stack pointer.
bool IgnoreLiveness = false;
- // StackOffset is the canonical location on stack (only if
- // RegNum==NoRegister || IsArgument).
+ /// StackOffset is the canonical location on stack (only if
+ /// RegNum==NoRegister || IsArgument).
int32_t StackOffset = 0;
- // RegNum is the allocated register, or NoRegister if it isn't
- // register-allocated.
+ /// RegNum is the allocated register, or NoRegister if it isn't
+ /// register-allocated.
int32_t RegNum = NoRegister;
- // RegNumTmp is the tentative assignment during register allocation.
+ /// RegNumTmp is the tentative assignment during register allocation.
int32_t RegNumTmp = NoRegister;
RegWeight Weight = RegWeight(1); // Register allocation priority
LiveRange Live;
@@ -538,20 +544,20 @@
// wasteful for a 64-bit target.
Variable *LoVar = nullptr;
Variable *HiVar = nullptr;
- // VarsReal (and Operand::Vars) are set up such that Vars[0] ==
- // this.
+ /// VarsReal (and Operand::Vars) are set up such that Vars[0] ==
+ /// this.
Variable *VarsReal[1];
};
enum MetadataKind {
- VMK_Uses, // Track only uses, not defs
- VMK_SingleDefs, // Track uses+defs, but only record single def
- VMK_All // Track uses+defs, including full def list
+ VMK_Uses, /// Track only uses, not defs
+ VMK_SingleDefs, /// Track uses+defs, but only record single def
+ VMK_All /// Track uses+defs, including full def list
};
typedef std::vector<const Inst *, CfgLocalAllocator<const Inst *>> InstDefList;
-// VariableTracking tracks the metadata for a single variable. It is
-// only meant to be used internally by VariablesMetadata.
+/// VariableTracking tracks the metadata for a single variable. It is
+/// only meant to be used internally by VariablesMetadata.
class VariableTracking {
VariableTracking &operator=(const VariableTracking &) = delete;
@@ -582,15 +588,15 @@
MultiBlockState MultiBlock = MBS_Unknown;
const CfgNode *SingleUseNode = nullptr;
const CfgNode *SingleDefNode = nullptr;
- // All definitions of the variable are collected here, in increasing
- // order of instruction number.
- InstDefList Definitions; // Only used if Kind==VMK_All
+ /// All definitions of the variable are collected here, in increasing
+ /// order of instruction number.
+ InstDefList Definitions; /// Only used if Kind==VMK_All
const Inst *FirstOrSingleDefinition =
- nullptr; // Is a copy of Definitions[0] if Kind==VMK_All
+ nullptr; /// Is a copy of Definitions[0] if Kind==VMK_All
};
-// VariablesMetadata analyzes and summarizes the metadata for the
-// complete set of Variables.
+/// VariablesMetadata analyzes and summarizes the metadata for the
+/// complete set of Variables.
class VariablesMetadata {
VariablesMetadata() = delete;
VariablesMetadata(const VariablesMetadata &) = delete;
@@ -598,47 +604,47 @@
public:
explicit VariablesMetadata(const Cfg *Func) : Func(Func) {}
- // Initialize the state by traversing all instructions/variables in
- // the CFG.
+ /// Initialize the state by traversing all instructions/variables in
+ /// the CFG.
void init(MetadataKind TrackingKind);
- // Add a single node. This is called by init(), and can be called
- // incrementally from elsewhere, e.g. after edge-splitting.
+ /// Add a single node. This is called by init(), and can be called
+ /// incrementally from elsewhere, e.g. after edge-splitting.
void addNode(CfgNode *Node);
- // Returns whether the given Variable is tracked in this object. It
- // should only return false if changes were made to the CFG after
- // running init(), in which case the state is stale and the results
- // shouldn't be trusted (but it may be OK e.g. for dumping).
+ /// Returns whether the given Variable is tracked in this object. It
+ /// should only return false if changes were made to the CFG after
+ /// running init(), in which case the state is stale and the results
+ /// shouldn't be trusted (but it may be OK e.g. for dumping).
bool isTracked(const Variable *Var) const {
return Var->getIndex() < Metadata.size();
}
- // Returns whether the given Variable has multiple definitions.
+ /// Returns whether the given Variable has multiple definitions.
bool isMultiDef(const Variable *Var) const;
- // Returns the first definition instruction of the given Variable.
- // This is only valid for variables whose definitions are all within
- // the same block, e.g. T after the lowered sequence "T=B; T+=C;
- // A=T", for which getFirstDefinition(T) would return the "T=B"
- // instruction. For variables with definitions span multiple
- // blocks, nullptr is returned.
+ /// Returns the first definition instruction of the given Variable.
+ /// This is only valid for variables whose definitions are all within
+ /// the same block, e.g. T after the lowered sequence "T=B; T+=C;
+ /// A=T", for which getFirstDefinition(T) would return the "T=B"
+ /// instruction. For variables with definitions span multiple
+ /// blocks, nullptr is returned.
const Inst *getFirstDefinition(const Variable *Var) const;
- // Returns the definition instruction of the given Variable, when
- // the variable has exactly one definition. Otherwise, nullptr is
- // returned.
+ /// Returns the definition instruction of the given Variable, when
+ /// the variable has exactly one definition. Otherwise, nullptr is
+ /// returned.
const Inst *getSingleDefinition(const Variable *Var) const;
- // Returns the list of all definition instructions of the given
- // Variable.
+ /// Returns the list of all definition instructions of the given
+ /// Variable.
const InstDefList &getLatterDefinitions(const Variable *Var) const;
- // Returns whether the given Variable is live across multiple
- // blocks. Mainly, this is used to partition Variables into
- // single-block versus multi-block sets for leveraging sparsity in
- // liveness analysis, and for implementing simple stack slot
- // coalescing. As a special case, function arguments are always
- // considered multi-block because they are live coming into the
- // entry block.
+ /// Returns whether the given Variable is live across multiple
+ /// blocks. Mainly, this is used to partition Variables into
+ /// single-block versus multi-block sets for leveraging sparsity in
+ /// liveness analysis, and for implementing simple stack slot
+ /// coalescing. As a special case, function arguments are always
+ /// considered multi-block because they are live coming into the
+ /// entry block.
bool isMultiBlock(const Variable *Var) const;
- // Returns the node that the given Variable is used in, assuming
- // isMultiBlock() returns false. Otherwise, nullptr is returned.
+ /// Returns the node that the given Variable is used in, assuming
+ /// isMultiBlock() returns false. Otherwise, nullptr is returned.
const CfgNode *getLocalUseNode(const Variable *Var) const;
private:
diff --git a/src/IceRNG.cpp b/src/IceRNG.cpp
index e3fa8c5..a6b9adf 100644
--- a/src/IceRNG.cpp
+++ b/src/IceRNG.cpp
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the random number generator.
-//
+///
+/// \file
+/// This file implements the random number generator.
+///
//===----------------------------------------------------------------------===//
#include "IceRNG.h"
diff --git a/src/IceRNG.h b/src/IceRNG.h
index 83001ad..5ddd97f 100644
--- a/src/IceRNG.h
+++ b/src/IceRNG.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares a random number generator.
-//
+///
+/// \file
+/// This file declares a random number generator.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICERNG_H
@@ -33,9 +34,9 @@
uint64_t State;
};
-// This class adds additional random number generator utilities. The
-// reason for the wrapper class is that we want to keep the
-// RandomNumberGenerator interface identical to LLVM's.
+/// This class adds additional random number generator utilities. The
+/// reason for the wrapper class is that we want to keep the
+/// RandomNumberGenerator interface identical to LLVM's.
class RandomNumberGeneratorWrapper {
RandomNumberGeneratorWrapper() = delete;
RandomNumberGeneratorWrapper(const RandomNumberGeneratorWrapper &) = delete;
@@ -52,9 +53,9 @@
RandomNumberGenerator &RNG;
};
-// RandomShuffle is an implementation of std::random_shuffle() that
-// doesn't change across stdlib implementations. Adapted from a
-// sample implementation at cppreference.com.
+/// RandomShuffle is an implementation of std::random_shuffle() that
+/// doesn't change across stdlib implementations. Adapted from a
+/// sample implementation at cppreference.com.
template <class RandomIt, class RandomFunc>
void RandomShuffle(RandomIt First, RandomIt Last, RandomFunc &&RNG) {
for (auto i = Last - First - 1; i > 0; --i)
diff --git a/src/IceRegAlloc.cpp b/src/IceRegAlloc.cpp
index 1478b0f..400cb7d 100644
--- a/src/IceRegAlloc.cpp
+++ b/src/IceRegAlloc.cpp
@@ -6,11 +6,12 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the LinearScan class, which performs the
-// linear-scan register allocation after liveness analysis has been
-// performed.
-//
+///
+/// \file
+/// This file implements the LinearScan class, which performs the
+/// linear-scan register allocation after liveness analysis has been
+/// performed.
+///
//===----------------------------------------------------------------------===//
#include "IceRegAlloc.h"
diff --git a/src/IceRegAlloc.h b/src/IceRegAlloc.h
index 1658a7d..89ae715 100644
--- a/src/IceRegAlloc.h
+++ b/src/IceRegAlloc.h
@@ -6,11 +6,12 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the LinearScan data structure used during
-// linear-scan register allocation, which holds the various work
-// queues for the linear-scan algorithm.
-//
+///
+/// \file
+/// This file declares the LinearScan data structure used during
+/// linear-scan register allocation, which holds the various work
+/// queues for the linear-scan algorithm.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEREGALLOC_H
@@ -38,12 +39,12 @@
void initForGlobal();
void initForInfOnly();
- // Move an item from the From set to the To set. From[Index] is
- // pushed onto the end of To[], then the item is efficiently removed
- // from From[] by effectively swapping it with the last item in
- // From[] and then popping it from the back. As such, the caller is
- // best off iterating over From[] in reverse order to avoid the need
- // for special handling of the iterator.
+ /// Move an item from the From set to the To set. From[Index] is
+ /// pushed onto the end of To[], then the item is efficiently removed
+ /// from From[] by effectively swapping it with the last item in
+ /// From[] and then popping it from the back. As such, the caller is
+ /// best off iterating over From[] in reverse order to avoid the need
+ /// for special handling of the iterator.
void moveItem(UnorderedRanges &From, SizeT Index, UnorderedRanges &To) {
To.push_back(From[Index]);
From[Index] = From.back();
@@ -52,8 +53,8 @@
Cfg *const Func;
OrderedRanges Unhandled;
- // UnhandledPrecolored is a subset of Unhandled, specially collected
- // for faster processing.
+ /// UnhandledPrecolored is a subset of Unhandled, specially collected
+ /// for faster processing.
OrderedRanges UnhandledPrecolored;
UnorderedRanges Active, Inactive, Handled;
std::vector<InstNumberT> Kills;
diff --git a/src/IceRegistersARM32.h b/src/IceRegistersARM32.h
index 2ad1c8b..39efd7f 100644
--- a/src/IceRegistersARM32.h
+++ b/src/IceRegistersARM32.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the registers and their encodings for ARM32.
-//
+///
+/// \file
+/// This file declares the registers and their encodings for ARM32.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEREGISTERSARM32_H
@@ -22,8 +23,8 @@
namespace RegARM32 {
-// An enum of every register. The enum value may not match the encoding
-// used to binary encode register operands in instructions.
+/// An enum of every register. The enum value may not match the encoding
+/// used to binary encode register operands in instructions.
enum AllRegisters {
#define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \
isFP) \
@@ -36,8 +37,8 @@
#undef X
};
-// An enum of GPR Registers. The enum value does match the encoding used
-// to binary encode register operands in instructions.
+/// An enum of GPR Registers. The enum value does match the encoding used
+/// to binary encode register operands in instructions.
enum GPRRegister {
#define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \
isFP) \
diff --git a/src/IceRegistersMIPS32.h b/src/IceRegistersMIPS32.h
index d2180bf..8c75488 100644
--- a/src/IceRegistersMIPS32.h
+++ b/src/IceRegistersMIPS32.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the registers and their encodings for MIPS32.
-//
+///
+/// \file
+/// This file declares the registers and their encodings for MIPS32.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEREGISTERSMIPS32_H
@@ -22,8 +23,8 @@
namespace RegMIPS32 {
-// An enum of every register. The enum value may not match the encoding
-// used to binary encode register operands in instructions.
+/// An enum of every register. The enum value may not match the encoding
+/// used to binary encode register operands in instructions.
enum AllRegisters {
#define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \
isFP) \
@@ -36,8 +37,8 @@
#undef X
};
-// An enum of GPR Registers. The enum value does match the encoding used
-// to binary encode register operands in instructions.
+/// An enum of GPR Registers. The enum value does match the encoding used
+/// to binary encode register operands in instructions.
enum GPRRegister {
#define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \
isFP) \
diff --git a/src/IceRegistersX8632.h b/src/IceRegistersX8632.h
index d7bfd6f..7cce661 100644
--- a/src/IceRegistersX8632.h
+++ b/src/IceRegistersX8632.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the registers and their encodings for x86-32.
-//
+///
+/// \file
+/// This file declares the registers and their encodings for x86-32.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEREGISTERSX8632_H
@@ -22,8 +23,8 @@
class RegX8632 {
public:
- // An enum of every register. The enum value may not match the encoding
- // used to binary encode register operands in instructions.
+ /// An enum of every register. The enum value may not match the encoding
+ /// used to binary encode register operands in instructions.
enum AllRegisters {
#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
frameptr, isI8, isInt, isFP) \
@@ -36,8 +37,8 @@
#undef X
};
- // An enum of GPR Registers. The enum value does match the encoding used
- // to binary encode register operands in instructions.
+ /// An enum of GPR Registers. The enum value does match the encoding used
+ /// to binary encode register operands in instructions.
enum GPRRegister {
#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
frameptr, isI8, isInt, isFP) \
@@ -47,8 +48,8 @@
Encoded_Not_GPR = -1
};
- // An enum of XMM Registers. The enum value does match the encoding used
- // to binary encode register operands in instructions.
+ /// An enum of XMM Registers. The enum value does match the encoding used
+ /// to binary encode register operands in instructions.
enum XmmRegister {
#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
frameptr, isI8, isInt, isFP) \
@@ -58,8 +59,8 @@
Encoded_Not_Xmm = -1
};
- // An enum of Byte Registers. The enum value does match the encoding used
- // to binary encode register operands in instructions.
+ /// An enum of Byte Registers. The enum value does match the encoding used
+ /// to binary encode register operands in instructions.
enum ByteRegister {
#define X(val, encode) Encoded_##val encode,
REGX8632_BYTEREG_TABLE
@@ -67,8 +68,8 @@
Encoded_Not_ByteReg = -1
};
- // An enum of X87 Stack Registers. The enum value does match the encoding used
- // to binary encode register operands in instructions.
+ /// An enum of X87 Stack Registers. The enum value does match the encoding used
+ /// to binary encode register operands in instructions.
enum X87STRegister {
#define X(val, encode, name) Encoded_##val encode,
X87ST_REGX8632_TABLE
diff --git a/src/IceRegistersX8664.h b/src/IceRegistersX8664.h
index ceafc86..3e4c868 100644
--- a/src/IceRegistersX8664.h
+++ b/src/IceRegistersX8664.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the registers and their encodings for x86-64.
-//
+///
+/// \file
+/// This file declares the registers and their encodings for x86-64.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEREGISTERSX8664_H
@@ -22,8 +23,8 @@
class RegX8664 {
public:
- // An enum of every register. The enum value may not match the encoding
- // used to binary encode register operands in instructions.
+ /// An enum of every register. The enum value may not match the encoding
+ /// used to binary encode register operands in instructions.
enum AllRegisters {
#define X(val, encode, name64, name, name16, name8, scratch, preserved, \
stackptr, frameptr, isInt, isFP) \
@@ -36,8 +37,8 @@
#undef X
};
- // An enum of GPR Registers. The enum value does match the encoding used
- // to binary encode register operands in instructions.
+ /// An enum of GPR Registers. The enum value does match the encoding used
+ /// to binary encode register operands in instructions.
enum GPRRegister {
#define X(val, encode, name64, name, name16, name8, scratch, preserved, \
stackptr, frameptr, isInt, isFP) \
@@ -47,8 +48,8 @@
Encoded_Not_GPR = -1
};
- // An enum of XMM Registers. The enum value does match the encoding used
- // to binary encode register operands in instructions.
+ /// An enum of XMM Registers. The enum value does match the encoding used
+ /// to binary encode register operands in instructions.
enum XmmRegister {
#define X(val, encode, name64, name, name16, name8, scratch, preserved, \
stackptr, frameptr, isInt, isFP) \
@@ -58,8 +59,8 @@
Encoded_Not_Xmm = -1
};
- // An enum of Byte Registers. The enum value does match the encoding used
- // to binary encode register operands in instructions.
+ /// An enum of Byte Registers. The enum value does match the encoding used
+ /// to binary encode register operands in instructions.
enum ByteRegister {
#define X(val, encode) Encoded_##val encode,
REGX8664_BYTEREG_TABLE
diff --git a/src/IceTLS.h b/src/IceTLS.h
index ee1fe24..6837668 100644
--- a/src/IceTLS.h
+++ b/src/IceTLS.h
@@ -6,12 +6,13 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines macros for working around the lack of support for
-// thread_local in MacOS 10.6. It assumes std::thread is written in
-// terms of pthread. Define ICE_THREAD_LOCAL_HACK to enable the
-// pthread workarounds.
-//
+///
+/// \file
+/// This file defines macros for working around the lack of support for
+/// thread_local in MacOS 10.6. It assumes std::thread is written in
+/// terms of pthread. Define ICE_THREAD_LOCAL_HACK to enable the
+/// pthread workarounds.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICETLS_H
diff --git a/src/IceTargetLowering.cpp b/src/IceTargetLowering.cpp
index 33a914d..671bab0 100644
--- a/src/IceTargetLowering.cpp
+++ b/src/IceTargetLowering.cpp
@@ -6,13 +6,14 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the skeleton of the TargetLowering class,
-// specifically invoking the appropriate lowering method for a given
-// instruction kind and driving global register allocation. It also
-// implements the non-deleted instruction iteration in
-// LoweringContext.
-//
+///
+/// \file
+/// This file implements the skeleton of the TargetLowering class,
+/// specifically invoking the appropriate lowering method for a given
+/// instruction kind and driving global register allocation. It also
+/// implements the non-deleted instruction iteration in
+/// LoweringContext.
+///
//===----------------------------------------------------------------------===//
#include "IceTargetLowering.h"
diff --git a/src/IceTargetLowering.h b/src/IceTargetLowering.h
index b543208..64672c4 100644
--- a/src/IceTargetLowering.h
+++ b/src/IceTargetLowering.h
@@ -6,16 +6,17 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the TargetLowering, LoweringContext, and
-// TargetDataLowering classes. TargetLowering is an abstract class
-// used to drive the translation/lowering process. LoweringContext
-// maintains a context for lowering each instruction, offering
-// conveniences such as iterating over non-deleted instructions.
-// TargetDataLowering is an abstract class used to drive the
-// lowering/emission of global initializers, external global
-// declarations, and internal constant pools.
-//
+///
+/// \file
+/// This file declares the TargetLowering, LoweringContext, and
+/// TargetDataLowering classes. TargetLowering is an abstract class
+/// used to drive the translation/lowering process. LoweringContext
+/// maintains a context for lowering each instruction, offering
+/// conveniences such as iterating over non-deleted instructions.
+/// TargetDataLowering is an abstract class used to drive the
+/// lowering/emission of global initializers, external global
+/// declarations, and internal constant pools.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICETARGETLOWERING_H
@@ -28,12 +29,12 @@
namespace Ice {
-// LoweringContext makes it easy to iterate through non-deleted
-// instructions in a node, and insert new (lowered) instructions at
-// the current point. Along with the instruction list container and
-// associated iterators, it holds the current node, which is needed
-// when inserting new instructions in order to track whether variables
-// are used as single-block or multi-block.
+/// LoweringContext makes it easy to iterate through non-deleted
+/// instructions in a node, and insert new (lowered) instructions at
+/// the current point. Along with the instruction list container and
+/// associated iterators, it holds the current node, which is needed
+/// when inserting new instructions in order to track whether variables
+/// are used as single-block or multi-block.
class LoweringContext {
LoweringContext(const LoweringContext &) = delete;
LoweringContext &operator=(const LoweringContext &) = delete;
@@ -66,24 +67,24 @@
void setInsertPoint(const InstList::iterator &Position) { Next = Position; }
private:
- // Node is the argument to Inst::updateVars().
+ /// Node is the argument to Inst::updateVars().
CfgNode *Node = nullptr;
Inst *LastInserted = nullptr;
- // Cur points to the current instruction being considered. It is
- // guaranteed to point to a non-deleted instruction, or to be End.
+ /// Cur points to the current instruction being considered. It is
+ /// guaranteed to point to a non-deleted instruction, or to be End.
InstList::iterator Cur;
- // Next doubles as a pointer to the next valid instruction (if any),
- // and the new-instruction insertion point. It is also updated for
- // the caller in case the lowering consumes more than one high-level
- // instruction. It is guaranteed to point to a non-deleted
- // instruction after Cur, or to be End. TODO: Consider separating
- // the notion of "next valid instruction" and "new instruction
- // insertion point", to avoid confusion when previously-deleted
- // instructions come between the two points.
+ /// Next doubles as a pointer to the next valid instruction (if any),
+ /// and the new-instruction insertion point. It is also updated for
+ /// the caller in case the lowering consumes more than one high-level
+ /// instruction. It is guaranteed to point to a non-deleted
+ /// instruction after Cur, or to be End. TODO: Consider separating
+ /// the notion of "next valid instruction" and "new instruction
+ /// insertion point", to avoid confusion when previously-deleted
+ /// instructions come between the two points.
InstList::iterator Next;
- // Begin is a copy of Insts.begin(), used if iterators are moved backward.
+ /// Begin is a copy of Insts.begin(), used if iterators are moved backward.
InstList::iterator Begin;
- // End is a copy of Insts.end(), used if Next needs to be advanced.
+ /// End is a copy of Insts.end(), used if Next needs to be advanced.
InstList::iterator End;
void skipDeleted(InstList::iterator &I) const;
@@ -129,37 +130,37 @@
Func->setError("Target doesn't specify O2 lowering steps.");
}
- // Tries to do address mode optimization on a single instruction.
+ /// Tries to do address mode optimization on a single instruction.
void doAddressOpt();
- // Randomly insert NOPs.
+ /// Randomly insert NOPs.
void doNopInsertion();
- // Lowers a single non-Phi instruction.
+ /// Lowers a single non-Phi instruction.
void lower();
- // Does preliminary lowering of the set of Phi instructions in the
- // current node. The main intention is to do what's needed to keep
- // the unlowered Phi instructions consistent with the lowered
- // non-Phi instructions, e.g. to lower 64-bit operands on a 32-bit
- // target.
+ /// Does preliminary lowering of the set of Phi instructions in the
+ /// current node. The main intention is to do what's needed to keep
+ /// the unlowered Phi instructions consistent with the lowered
+ /// non-Phi instructions, e.g. to lower 64-bit operands on a 32-bit
+ /// target.
virtual void prelowerPhis() {}
- // Lowers a list of "parallel" assignment instructions representing
- // a topological sort of the Phi instructions.
+ /// Lowers a list of "parallel" assignment instructions representing
+ /// a topological sort of the Phi instructions.
virtual void lowerPhiAssignments(CfgNode *Node,
const AssignList &Assignments) = 0;
- // Tries to do branch optimization on a single instruction. Returns
- // true if some optimization was done.
+ /// Tries to do branch optimization on a single instruction. Returns
+ /// true if some optimization was done.
virtual bool doBranchOpt(Inst * /*I*/, const CfgNode * /*NextNode*/) {
return false;
}
virtual SizeT getNumRegisters() const = 0;
- // Returns a variable pre-colored to the specified physical
- // register. This is generally used to get very direct access to
- // the register such as in the prolog or epilog or for marking
- // scratch registers as killed by a call. If a Type is not
- // provided, a target-specific default type is used.
+ /// Returns a variable pre-colored to the specified physical
+ /// register. This is generally used to get very direct access to
+ /// the register such as in the prolog or epilog or for marking
+ /// scratch registers as killed by a call. If a Type is not
+ /// provided, a target-specific default type is used.
virtual Variable *getPhysicalRegister(SizeT RegNum,
Type Ty = IceType_void) = 0;
- // Returns a printable name for the register.
+ /// Returns a printable name for the register.
virtual IceString getRegName(SizeT RegNum, Type Ty) const = 0;
virtual bool hasFramePointer() const { return false; }
@@ -167,8 +168,8 @@
virtual size_t typeWidthInBytesOnStack(Type Ty) const = 0;
bool hasComputedFrame() const { return HasComputedFrame; }
- // Returns true if this function calls a function that has the
- // "returns twice" attribute.
+ /// Returns true if this function calls a function that has the
+ /// "returns twice" attribute.
bool callsReturnsTwice() const { return CallsReturnsTwice; }
void setCallsReturnsTwice(bool RetTwice) { CallsReturnsTwice = RetTwice; }
int32_t getStackAdjustment() const { return StackAdjustment; }
@@ -196,10 +197,10 @@
llvm::SmallVectorImpl<int32_t> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters) const = 0;
- // Save/restore any mutable state for the situation where code
- // emission needs multiple passes, such as sandboxing or relaxation.
- // Subclasses may provide their own implementation, but should be
- // sure to also call the parent class's methods.
+ /// Save/restore any mutable state for the situation where code
+ /// emission needs multiple passes, such as sandboxing or relaxation.
+ /// Subclasses may provide their own implementation, but should be
+ /// sure to also call the parent class's methods.
virtual void snapshotEmitState() {
SnapshotStackAdjustment = StackAdjustment;
}
@@ -219,7 +220,7 @@
virtual void emit(const ConstantFloat *C) const = 0;
virtual void emit(const ConstantDouble *C) const = 0;
- // Performs target-specific argument lowering.
+ /// Performs target-specific argument lowering.
virtual void lowerArguments() = 0;
virtual void initNodeForLowering(CfgNode *) {}
@@ -253,30 +254,30 @@
virtual void doAddressOptLoad() {}
virtual void doAddressOptStore() {}
virtual void randomlyInsertNop(float Probability) = 0;
- // This gives the target an opportunity to post-process the lowered
- // expansion before returning.
+ /// This gives the target an opportunity to post-process the lowered
+ /// expansion before returning.
virtual void postLower() {}
- // Find two-address non-SSA instructions and set the DestNonKillable flag
- // to keep liveness analysis consistent.
+ /// Find two-address non-SSA instructions and set the DestNonKillable flag
+ /// to keep liveness analysis consistent.
void inferTwoAddress();
- // Make a pass over the Cfg to determine which variables need stack slots
- // and place them in a sorted list (SortedSpilledVariables). Among those,
- // vars, classify the spill variables as local to the basic block vs
- // global (multi-block) in order to compute the parameters GlobalsSize
- // and SpillAreaSizeBytes (represents locals or general vars if the
- // coalescing of locals is disallowed) along with alignments required
- // for variables in each area. We rely on accurate VMetadata in order to
- // classify a variable as global vs local (otherwise the variable is
- // conservatively global). The in-args should be initialized to 0.
- //
- // This is only a pre-pass and the actual stack slot assignment is
- // handled separately.
- //
- // There may be target-specific Variable types, which will be handled
- // by TargetVarHook. If the TargetVarHook returns true, then the variable
- // is skipped and not considered with the rest of the spilled variables.
+ /// Make a pass over the Cfg to determine which variables need stack slots
+ /// and place them in a sorted list (SortedSpilledVariables). Among those,
+ /// vars, classify the spill variables as local to the basic block vs
+ /// global (multi-block) in order to compute the parameters GlobalsSize
+ /// and SpillAreaSizeBytes (represents locals or general vars if the
+ /// coalescing of locals is disallowed) along with alignments required
+ /// for variables in each area. We rely on accurate VMetadata in order to
+ /// classify a variable as global vs local (otherwise the variable is
+ /// conservatively global). The in-args should be initialized to 0.
+ ///
+ /// This is only a pre-pass and the actual stack slot assignment is
+ /// handled separately.
+ ///
+ /// There may be target-specific Variable types, which will be handled
+ /// by TargetVarHook. If the TargetVarHook returns true, then the variable
+ /// is skipped and not considered with the rest of the spilled variables.
void getVarStackSlotParams(VarList &SortedSpilledVariables,
llvm::SmallBitVector &RegsUsed,
size_t *GlobalsSize, size_t *SpillAreaSizeBytes,
@@ -284,9 +285,9 @@
uint32_t *LocalsSlotsAlignmentBytes,
std::function<bool(Variable *)> TargetVarHook);
- // Calculate the amount of padding needed to align the local and global
- // areas to the required alignment. This assumes the globals/locals layout
- // used by getVarStackSlotParams and assignVarStackSlots.
+ /// Calculate the amount of padding needed to align the local and global
+ /// areas to the required alignment. This assumes the globals/locals layout
+ /// used by getVarStackSlotParams and assignVarStackSlots.
void alignStackSpillAreas(uint32_t SpillAreaStartOffset,
uint32_t SpillAreaAlignmentBytes,
size_t GlobalsSize,
@@ -294,24 +295,24 @@
uint32_t *SpillAreaPaddingBytes,
uint32_t *LocalsSlotsPaddingBytes);
- // Make a pass through the SortedSpilledVariables and actually assign
- // stack slots. SpillAreaPaddingBytes takes into account stack alignment
- // padding. The SpillArea starts after that amount of padding.
- // This matches the scheme in getVarStackSlotParams, where there may
- // be a separate multi-block global var spill area and a local var
- // spill area.
+ /// Make a pass through the SortedSpilledVariables and actually assign
+ /// stack slots. SpillAreaPaddingBytes takes into account stack alignment
+ /// padding. The SpillArea starts after that amount of padding.
+ /// This matches the scheme in getVarStackSlotParams, where there may
+ /// be a separate multi-block global var spill area and a local var
+ /// spill area.
void assignVarStackSlots(VarList &SortedSpilledVariables,
size_t SpillAreaPaddingBytes,
size_t SpillAreaSizeBytes,
size_t GlobalsAndSubsequentPaddingSize,
bool UsesFramePointer);
- // Sort the variables in Source based on required alignment.
- // The variables with the largest alignment need are placed in the front
- // of the Dest list.
+ /// Sort the variables in Source based on required alignment.
+ /// The variables with the largest alignment need are placed in the front
+ /// of the Dest list.
void sortVarsByAlignment(VarList &Dest, const VarList &Source) const;
- // Make a call to an external helper function.
+ /// Make a call to an external helper function.
InstCall *makeHelperCall(const IceString &Name, Variable *Dest,
SizeT MaxSrcs);
@@ -325,8 +326,8 @@
GlobalContext *Ctx;
bool HasComputedFrame = false;
bool CallsReturnsTwice = false;
- // StackAdjustment keeps track of the current stack offset from its
- // natural location, as arguments are pushed for a function call.
+ /// StackAdjustment keeps track of the current stack offset from its
+ /// natural location, as arguments are pushed for a function call.
int32_t StackAdjustment = 0;
SizeT NextLabelNumber = 0;
LoweringContext Context;
@@ -373,9 +374,9 @@
int32_t SnapshotStackAdjustment = 0;
};
-// TargetDataLowering is used for "lowering" data including initializers
-// for global variables, and the internal constant pools. It is separated
-// out from TargetLowering because it does not require a Cfg.
+/// TargetDataLowering is used for "lowering" data including initializers
+/// for global variables, and the internal constant pools. It is separated
+/// out from TargetLowering because it does not require a Cfg.
class TargetDataLowering {
TargetDataLowering() = delete;
TargetDataLowering(const TargetDataLowering &) = delete;
@@ -393,18 +394,18 @@
void emitGlobal(const VariableDeclaration &Var,
const IceString &SectionSuffix);
- // For now, we assume .long is the right directive for emitting 4 byte
- // emit global relocations. However, LLVM MIPS usually uses .4byte instead.
- // Perhaps there is some difference when the location is unaligned.
+ /// For now, we assume .long is the right directive for emitting 4 byte
+ /// emit global relocations. However, LLVM MIPS usually uses .4byte instead.
+ /// Perhaps there is some difference when the location is unaligned.
static const char *getEmit32Directive() { return ".long"; }
explicit TargetDataLowering(GlobalContext *Ctx) : Ctx(Ctx) {}
GlobalContext *Ctx;
};
-// TargetHeaderLowering is used to "lower" the header of an output file.
-// It writes out the target-specific header attributes. E.g., for ARM
-// this writes out the build attributes (float ABI, etc.).
+/// TargetHeaderLowering is used to "lower" the header of an output file.
+/// It writes out the target-specific header attributes. E.g., for ARM
+/// this writes out the build attributes (float ABI, etc.).
class TargetHeaderLowering {
TargetHeaderLowering() = delete;
TargetHeaderLowering(const TargetHeaderLowering &) = delete;
diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp
index 85294b0..6639da8 100644
--- a/src/IceTargetLoweringARM32.cpp
+++ b/src/IceTargetLoweringARM32.cpp
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the TargetLoweringARM32 class, which consists almost
-// entirely of the lowering sequence for each high-level instruction.
-//
+///
+/// \file
+/// This file implements the TargetLoweringARM32 class, which consists almost
+/// entirely of the lowering sequence for each high-level instruction.
+///
//===----------------------------------------------------------------------===//
#include "IceTargetLoweringARM32.h"
diff --git a/src/IceTargetLoweringARM32.h b/src/IceTargetLoweringARM32.h
index 02d9080..8aa3e11 100644
--- a/src/IceTargetLoweringARM32.h
+++ b/src/IceTargetLoweringARM32.h
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the TargetLoweringARM32 class, which implements the
-// TargetLowering interface for the ARM 32-bit architecture.
-//
+///
+/// \file
+/// This file declares the TargetLoweringARM32 class, which implements the
+/// TargetLowering interface for the ARM 32-bit architecture.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICETARGETLOWERINGARM32_H
@@ -90,9 +91,9 @@
void addProlog(CfgNode *Node) override;
void addEpilog(CfgNode *Node) override;
- // Ensure that a 64-bit Variable has been split into 2 32-bit
- // Variables, creating them if necessary. This is needed for all
- // I64 operations.
+ /// Ensure that a 64-bit Variable has been split into 2 32-bit
+ /// Variables, creating them if necessary. This is needed for all
+ /// I64 operations.
void split64(Variable *Var);
Operand *loOperand(Operand *Operand);
Operand *hiOperand(Operand *Operand);
@@ -135,10 +136,10 @@
enum OperandLegalization {
Legal_None = 0,
- Legal_Reg = 1 << 0, // physical register, not stack location
- Legal_Flex = 1 << 1, // A flexible operand2, which can hold rotated
- // small immediates, or shifted registers.
- Legal_Mem = 1 << 2, // includes [r0, r1 lsl #2] as well as [sp, #12]
+ Legal_Reg = 1 << 0, /// physical register, not stack location
+ Legal_Flex = 1 << 1, /// A flexible operand2, which can hold rotated
+ /// small immediates, or shifted registers.
+ Legal_Mem = 1 << 2, /// includes [r0, r1 lsl #2] as well as [sp, #12]
Legal_All = ~Legal_None
};
typedef uint32_t LegalMask;
@@ -152,7 +153,7 @@
Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister);
void alignRegisterPow2(Variable *Reg, uint32_t Align);
- // Returns a vector in a register with the given constant entries.
+ /// Returns a vector in a register with the given constant entries.
Variable *makeVectorOfZeros(Type Ty, int32_t RegNum = Variable::NoRegister);
void makeRandomRegisterPermutation(
@@ -247,9 +248,9 @@
CondARM32::Cond Pred = CondARM32::AL) {
Context.insert(InstARM32Mls::create(Func, Dest, Src0, Src1, Acc, Pred));
}
- // If Dest=nullptr is passed in, then a new variable is created,
- // marked as infinite register allocation weight, and returned
- // through the in/out Dest argument.
+ /// If Dest=nullptr is passed in, then a new variable is created,
+ /// marked as infinite register allocation weight, and returned
+ /// through the in/out Dest argument.
void _mov(Variable *&Dest, Operand *Src0,
CondARM32::Cond Pred = CondARM32::AL,
int32_t RegNum = Variable::NoRegister) {
@@ -263,8 +264,8 @@
NewInst->setDestNonKillable();
Context.insert(NewInst);
}
- // The Operand can only be a 16-bit immediate or a ConstantRelocatable
- // (with an upper16 relocation).
+ /// The Operand can only be a 16-bit immediate or a ConstantRelocatable
+ /// (with an upper16 relocation).
void _movt(Variable *Dest, Operand *Src0,
CondARM32::Cond Pred = CondARM32::AL) {
Context.insert(InstARM32Movt::create(Func, Dest, Src0, Pred));
@@ -372,16 +373,16 @@
VarList PhysicalRegisters[IceType_NUM];
static IceString RegNames[];
- // Helper class that understands the Calling Convention and register
- // assignments. The first few integer type parameters can use r0-r3,
- // regardless of their position relative to the floating-point/vector
- // arguments in the argument list. Floating-point and vector arguments
- // can use q0-q3 (aka d0-d7, s0-s15). Technically, arguments that can
- // start with registers but extend beyond the available registers can be
- // split between the registers and the stack. However, this is typically
- // for passing GPR structs by value, and PNaCl transforms expand this out.
- //
- // Also, at the point before the call, the stack must be aligned.
+ /// Helper class that understands the Calling Convention and register
+ /// assignments. The first few integer type parameters can use r0-r3,
+ /// regardless of their position relative to the floating-point/vector
+ /// arguments in the argument list. Floating-point and vector arguments
+ /// can use q0-q3 (aka d0-d7, s0-s15). Technically, arguments that can
+ /// start with registers but extend beyond the available registers can be
+ /// split between the registers and the stack. However, this is typically
+ /// for passing GPR structs by value, and PNaCl transforms expand this out.
+ ///
+ /// Also, at the point before the call, the stack must be aligned.
class CallingConv {
CallingConv(const CallingConv &) = delete;
CallingConv &operator=(const CallingConv &) = delete;
diff --git a/src/IceTargetLoweringMIPS32.cpp b/src/IceTargetLoweringMIPS32.cpp
index 0adff03..6c0793f 100644
--- a/src/IceTargetLoweringMIPS32.cpp
+++ b/src/IceTargetLoweringMIPS32.cpp
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the TargetLoweringMIPS32 class, which consists almost
-// entirely of the lowering sequence for each high-level instruction.
-//
+///
+/// \file
+/// This file implements the TargetLoweringMIPS32 class, which consists almost
+/// entirely of the lowering sequence for each high-level instruction.
+///
//===----------------------------------------------------------------------===//
#include "IceTargetLoweringMIPS32.h"
diff --git a/src/IceTargetLoweringMIPS32.h b/src/IceTargetLoweringMIPS32.h
index eb4a9fd..f872af0 100644
--- a/src/IceTargetLoweringMIPS32.h
+++ b/src/IceTargetLoweringMIPS32.h
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the TargetLoweringMIPS32 class, which implements the
-// TargetLowering interface for the MIPS 32-bit architecture.
-//
+///
+/// \file
+/// This file declares the TargetLoweringMIPS32 class, which implements the
+/// TargetLowering interface for the MIPS 32-bit architecture.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICETARGETLOWERINGMIPS32_H
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp
index e33eeef..c6a72d6 100644
--- a/src/IceTargetLoweringX8632.cpp
+++ b/src/IceTargetLoweringX8632.cpp
@@ -6,11 +6,12 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the TargetLoweringX8632 class, which
-// consists almost entirely of the lowering sequence for each
-// high-level instruction.
-//
+///
+/// \file
+/// This file implements the TargetLoweringX8632 class, which
+/// consists almost entirely of the lowering sequence for each
+/// high-level instruction.
+///
//===----------------------------------------------------------------------===//
#include "IceTargetLoweringX8632.h"
diff --git a/src/IceTargetLoweringX8632.h b/src/IceTargetLoweringX8632.h
index f24275d..f1d8bb3 100644
--- a/src/IceTargetLoweringX8632.h
+++ b/src/IceTargetLoweringX8632.h
@@ -6,11 +6,12 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the TargetLoweringX8632 class, which
-// implements the TargetLowering interface for the x86-32
-// architecture.
-//
+///
+/// \file
+/// This file declares the TargetLoweringX8632 class, which
+/// implements the TargetLowering interface for the x86-32
+/// architecture.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICETARGETLOWERINGX8632_H
diff --git a/src/IceTargetLoweringX8664.cpp b/src/IceTargetLoweringX8664.cpp
index 21be080..f2be0c1 100644
--- a/src/IceTargetLoweringX8664.cpp
+++ b/src/IceTargetLoweringX8664.cpp
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// Implements the Target Lowering for x86-64.
-//
+///
+/// \file
+/// Implements the Target Lowering for x86-64.
+///
//===----------------------------------------------------------------------===//
#include "IceDefs.h"
diff --git a/src/IceTargetLoweringX8664.h b/src/IceTargetLoweringX8664.h
index 0107cfc..791343a 100644
--- a/src/IceTargetLoweringX8664.h
+++ b/src/IceTargetLoweringX8664.h
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the TargetLoweringX8664 class, which implements the
-// TargetLowering interface for the X86 64-bit architecture.
-//
+///
+/// \file
+/// This file declares the TargetLoweringX8664 class, which implements the
+/// TargetLowering interface for the X86 64-bit architecture.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICETARGETLOWERINGX8664_H
diff --git a/src/IceTargetLoweringX86Base.h b/src/IceTargetLoweringX86Base.h
index 46c53f8..37a1107 100644
--- a/src/IceTargetLoweringX86Base.h
+++ b/src/IceTargetLoweringX86Base.h
@@ -6,11 +6,12 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the TargetLoweringX86 template class, which
-// implements the TargetLowering base interface for the x86
-// architecture.
-//
+///
+/// \file
+/// This file declares the TargetLoweringX86 template class, which
+/// implements the TargetLowering base interface for the x86
+/// architecture.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H
@@ -141,11 +142,11 @@
void initNodeForLowering(CfgNode *Node) override;
void addProlog(CfgNode *Node) override;
void addEpilog(CfgNode *Node) override;
- // Ensure that a 64-bit Variable has been split into 2 32-bit
- // Variables, creating them if necessary. This is needed for all
- // I64 operations, and it is needed for pushing F64 arguments for
- // function calls using the 32-bit push instruction (though the
- // latter could be done by directly writing to the stack).
+ /// Ensure that a 64-bit Variable has been split into 2 32-bit
+ /// Variables, creating them if necessary. This is needed for all
+ /// I64 operations, and it is needed for pushing F64 arguments for
+ /// function calls using the 32-bit push instruction (though the
+ /// latter could be done by directly writing to the stack).
void split64(Variable *Var);
Operand *loOperand(Operand *Operand);
Operand *hiOperand(Operand *Operand);
@@ -190,10 +191,10 @@
void doAddressOptStore() override;
void randomlyInsertNop(float Probability) override;
- // Naive lowering of cmpxchg.
+ /// Naive lowering of cmpxchg.
void lowerAtomicCmpxchg(Variable *DestPrev, Operand *Ptr, Operand *Expected,
Operand *Desired);
- // Attempt a more optimized lowering of cmpxchg. Returns true if optimized.
+ /// Attempt a more optimized lowering of cmpxchg. Returns true if optimized.
bool tryOptimizedCmpxchgCmpBr(Variable *DestPrev, Operand *Ptr,
Operand *Expected, Operand *Desired);
void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr,
@@ -210,13 +211,13 @@
void scalarizeArithmetic(InstArithmetic::OpKind K, Variable *Dest,
Operand *Src0, Operand *Src1);
- // Operand legalization helpers. To deal with address mode
- // constraints, the helpers will create a new Operand and emit
- // instructions that guarantee that the Operand kind is one of those
- // indicated by the LegalMask (a bitmask of allowed kinds). If the
- // input Operand is known to already meet the constraints, it may be
- // simply returned as the result, without creating any new
- // instructions or operands.
+ /// Operand legalization helpers. To deal with address mode
+ /// constraints, the helpers will create a new Operand and emit
+ /// instructions that guarantee that the Operand kind is one of those
+ /// indicated by the LegalMask (a bitmask of allowed kinds). If the
+ /// input Operand is known to already meet the constraints, it may be
+ /// simply returned as the result, without creating any new
+ /// instructions or operands.
enum OperandLegalization {
Legal_None = 0,
Legal_Reg = 1 << 0, // physical register, not stack location
@@ -228,11 +229,11 @@
Operand *legalize(Operand *From, LegalMask Allowed = Legal_All,
int32_t RegNum = Variable::NoRegister);
Variable *legalizeToVar(Operand *From, int32_t RegNum = Variable::NoRegister);
- // Legalize the first source operand for use in the cmp instruction.
+ /// Legalize the first source operand for use in the cmp instruction.
Operand *legalizeSrc0ForCmp(Operand *Src0, Operand *Src1);
- // Turn a pointer operand into a memory operand that can be
- // used by a real load/store operation. Legalizes the operand as well.
- // This is a nop if the operand is already a legal memory operand.
+ /// Turn a pointer operand into a memory operand that can be
+ /// used by a real load/store operation. Legalizes the operand as well.
+ /// This is a nop if the operand is already a legal memory operand.
OperandX8632Mem *formMemoryOperand(Operand *Ptr, Type Ty,
bool DoLegalize = true);
@@ -241,7 +242,7 @@
Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister);
- // Returns a vector in a register with the given constant entries.
+ /// Returns a vector in a register with the given constant entries.
Variable *makeVectorOfZeros(Type Ty, int32_t RegNum = Variable::NoRegister);
Variable *makeVectorOfOnes(Type Ty, int32_t RegNum = Variable::NoRegister);
Variable *makeVectorOfMinusOnes(Type Ty,
@@ -251,7 +252,7 @@
Variable *makeVectorOfFabsMask(Type Ty,
int32_t RegNum = Variable::NoRegister);
- // Return a memory operand corresponding to a stack allocated Variable.
+ /// Return a memory operand corresponding to a stack allocated Variable.
OperandX8632Mem *getMemoryOperandForStackSlot(Type Ty, Variable *Slot,
uint32_t Offset = 0);
@@ -260,9 +261,9 @@
const llvm::SmallBitVector &ExcludeRegisters) const override;
// TODO(jpp): move the helper methods below to the MachineTraits.
- // The following are helpers that insert lowered x86 instructions
- // with minimal syntactic overhead, so that the lowering code can
- // look as close to assembly as practical.
+ /// The following are helpers that insert lowered x86 instructions
+ /// with minimal syntactic overhead, so that the lowering code can
+ /// look as close to assembly as practical.
void _adc(Variable *Dest, Operand *Src0) {
Context.insert(InstX8632Adc::create(Func, Dest, Src0));
}
@@ -385,9 +386,9 @@
Context.insert(InstX8632Lea::create(Func, Dest, Src0));
}
void _mfence() { Context.insert(InstX8632Mfence::create(Func)); }
- // If Dest=nullptr is passed in, then a new variable is created,
- // marked as infinite register allocation weight, and returned
- // through the in/out Dest argument.
+ /// If Dest=nullptr is passed in, then a new variable is created,
+ /// marked as infinite register allocation weight, and returned
+ /// through the in/out Dest argument.
void _mov(Variable *&Dest, Operand *Src0,
int32_t RegNum = Variable::NoRegister) {
if (Dest == nullptr)
@@ -601,7 +602,7 @@
VarList PhysicalRegisters[IceType_NUM];
static IceString RegNames[];
- // Randomize a given immediate operand
+ /// Randomize a given immediate operand
Operand *randomizeOrPoolImmediate(Constant *Immediate,
int32_t RegNum = Variable::NoRegister);
OperandX8632Mem *
diff --git a/src/IceTargetLoweringX86BaseImpl.h b/src/IceTargetLoweringX86BaseImpl.h
index 9ebeb62..6a0f3b3 100644
--- a/src/IceTargetLoweringX86BaseImpl.h
+++ b/src/IceTargetLoweringX86BaseImpl.h
@@ -6,11 +6,12 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the TargetLoweringX86Base class, which
-// consists almost entirely of the lowering sequence for each
-// high-level instruction.
-//
+///
+/// \file
+/// This file implements the TargetLoweringX86Base class, which
+/// consists almost entirely of the lowering sequence for each
+/// high-level instruction.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H
@@ -34,8 +35,8 @@
namespace Ice {
namespace X86Internal {
-// A helper class to ease the settings of RandomizationPoolingPause
-// to disable constant blinding or pooling for some translation phases.
+/// A helper class to ease the settings of RandomizationPoolingPause
+/// to disable constant blinding or pooling for some translation phases.
class BoolFlagSaver {
BoolFlagSaver() = delete;
BoolFlagSaver(const BoolFlagSaver &) = delete;
@@ -57,15 +58,15 @@
BoolFoldingEntry() = default;
explicit BoolFoldingEntry(Inst *I);
BoolFoldingEntry &operator=(const BoolFoldingEntry &) = default;
- // Instr is the instruction producing the i1-type variable of interest.
+ /// Instr is the instruction producing the i1-type variable of interest.
Inst *Instr = nullptr;
- // IsComplex is the cached result of BoolFolding::hasComplexLowering(Instr).
+ /// IsComplex is the cached result of BoolFolding::hasComplexLowering(Instr).
bool IsComplex = false;
- // IsLiveOut is initialized conservatively to true, and is set to false when
- // we encounter an instruction that ends Var's live range. We disable the
- // folding optimization when Var is live beyond this basic block. Note that
- // if liveness analysis is not performed (e.g. in Om1 mode), IsLiveOut will
- // always be true and the folding optimization will never be performed.
+ /// IsLiveOut is initialized conservatively to true, and is set to false when
+ /// we encounter an instruction that ends Var's live range. We disable the
+ /// folding optimization when Var is live beyond this basic block. Note that
+ /// if liveness analysis is not performed (e.g. in Om1 mode), IsLiveOut will
+ /// always be true and the folding optimization will never be performed.
bool IsLiveOut = true;
// NumUses counts the number of times Var is used as a source operand in the
// basic block. If IsComplex is true and there is more than one use of Var,
@@ -83,10 +84,10 @@
PK_Trunc
};
- // Currently the actual enum values are not used (other than CK_None), but we
- // go
- // ahead and produce them anyway for symmetry with the
- // BoolFoldingProducerKind.
+ /// Currently the actual enum values are not used (other than CK_None), but we
+ /// go
+ /// ahead and produce them anyway for symmetry with the
+ /// BoolFoldingProducerKind.
enum BoolFoldingConsumerKind { CK_None, CK_Br, CK_Select, CK_Sext, CK_Zext };
private:
@@ -103,13 +104,13 @@
void dump(const Cfg *Func) const;
private:
- // Returns true if Producers contains a valid entry for the given VarNum.
+ /// Returns true if Producers contains a valid entry for the given VarNum.
bool containsValid(SizeT VarNum) const {
auto Element = Producers.find(VarNum);
return Element != Producers.end() && Element->second.Instr != nullptr;
}
void setInvalid(SizeT VarNum) { Producers[VarNum].Instr = nullptr; }
- // Producers maps Variable::Number to a BoolFoldingEntry.
+ /// Producers maps Variable::Number to a BoolFoldingEntry.
std::unordered_map<SizeT, BoolFoldingEntry<MachineTraits>> Producers;
};
@@ -162,12 +163,12 @@
return CK_None;
}
-// Returns true if the producing instruction has a "complex" lowering
-// sequence. This generally means that its lowering sequence requires
-// more than one conditional branch, namely 64-bit integer compares
-// and some floating-point compares. When this is true, and there is
-// more than one consumer, we prefer to disable the folding
-// optimization because it minimizes branches.
+/// Returns true if the producing instruction has a "complex" lowering
+/// sequence. This generally means that its lowering sequence requires
+/// more than one conditional branch, namely 64-bit integer compares
+/// and some floating-point compares. When this is true, and there is
+/// more than one consumer, we prefer to disable the folding
+/// optimization because it minimizes branches.
template <class MachineTraits>
bool BoolFolding<MachineTraits>::hasComplexLowering(const Inst *Instr) {
switch (getProducerKind(Instr)) {
@@ -610,11 +611,11 @@
return Intrinsics::MemoryOrderInvalid;
}
-// Determines whether the dest of a Load instruction can be folded
-// into one of the src operands of a 2-operand instruction. This is
-// true as long as the load dest matches exactly one of the binary
-// instruction's src operands. Replaces Src0 or Src1 with LoadSrc if
-// the answer is true.
+/// Determines whether the dest of a Load instruction can be folded
+/// into one of the src operands of a 2-operand instruction. This is
+/// true as long as the load dest matches exactly one of the binary
+/// instruction's src operands. Replaces Src0 or Src1 with LoadSrc if
+/// the answer is true.
bool canFoldLoadIntoBinaryInst(Operand *LoadSrc, Variable *LoadDest,
Operand *&Src0, Operand *&Src1) {
if (Src0 == LoadDest && Src1 != LoadDest) {
@@ -852,15 +853,15 @@
}
}
-// Helper function for addProlog().
-//
-// This assumes Arg is an argument passed on the stack. This sets the
-// frame offset for Arg and updates InArgsSizeBytes according to Arg's
-// width. For an I64 arg that has been split into Lo and Hi components,
-// it calls itself recursively on the components, taking care to handle
-// Lo first because of the little-endian architecture. Lastly, this
-// function generates an instruction to copy Arg into its assigned
-// register if applicable.
+/// Helper function for addProlog().
+///
+/// This assumes Arg is an argument passed on the stack. This sets the
+/// frame offset for Arg and updates InArgsSizeBytes according to Arg's
+/// width. For an I64 arg that has been split into Lo and Hi components,
+/// it calls itself recursively on the components, taking care to handle
+/// Lo first because of the little-endian architecture. Lastly, this
+/// function generates an instruction to copy Arg into its assigned
+/// register if applicable.
template <class Machine>
void TargetX86Base<Machine>::finishArgumentLowering(Variable *Arg,
Variable *FramePtr,
@@ -1347,12 +1348,12 @@
_mov(Dest, esp);
}
-// Strength-reduce scalar integer multiplication by a constant (for
-// i32 or narrower) for certain constants. The lea instruction can be
-// used to multiply by 3, 5, or 9, and the lsh instruction can be used
-// to multiply by powers of 2. These can be combined such that
-// e.g. multiplying by 100 can be done as 2 lea-based multiplies by 5,
-// combined with left-shifting by 2.
+/// Strength-reduce scalar integer multiplication by a constant (for
+/// i32 or narrower) for certain constants. The lea instruction can be
+/// used to multiply by 3, 5, or 9, and the lsh instruction can be used
+/// to multiply by powers of 2. These can be combined such that
+/// e.g. multiplying by 100 can be done as 2 lea-based multiplies by 5,
+/// combined with left-shifting by 2.
template <class Machine>
bool TargetX86Base<Machine>::optimizeScalarMul(Variable *Dest, Operand *Src0,
int32_t Src1) {
@@ -2391,7 +2392,7 @@
_pcmpgt(T, Zeros);
_movp(Dest, T);
} else {
- // width = width(elty) - 1; dest = (src << width) >> width
+ /// width = width(elty) - 1; dest = (src << width) >> width
SizeT ShiftAmount =
Traits::X86_CHAR_BIT * typeWidthInBytes(typeElementType(DestTy)) -
1;
@@ -3939,10 +3940,10 @@
_mov(Dest, T_eax);
}
-// Lowers count {trailing, leading} zeros intrinsic.
-//
-// We could do constant folding here, but that should have
-// been done by the front-end/middle-end optimizations.
+/// Lowers count {trailing, leading} zeros intrinsic.
+///
+/// We could do constant folding here, but that should have
+/// been done by the front-end/middle-end optimizations.
template <class Machine>
void TargetX86Base<Machine>::lowerCountZeros(bool Cttz, Type Ty, Variable *Dest,
Operand *FirstVal,
@@ -4608,14 +4609,14 @@
lowerAssign(InstAssign::create(Func, Dest, T));
}
-// The following pattern occurs often in lowered C and C++ code:
-//
-// %cmp = fcmp/icmp pred <n x ty> %src0, %src1
-// %cmp.ext = sext <n x i1> %cmp to <n x ty>
-//
-// We can eliminate the sext operation by copying the result of pcmpeqd,
-// pcmpgtd, or cmpps (which produce sign extended results) to the result
-// of the sext operation.
+/// The following pattern occurs often in lowered C and C++ code:
+///
+/// %cmp = fcmp/icmp pred <n x ty> %src0, %src1
+/// %cmp.ext = sext <n x i1> %cmp to <n x ty>
+///
+/// We can eliminate the sext operation by copying the result of pcmpeqd,
+/// pcmpgtd, or cmpps (which produce sign extended results) to the result
+/// of the sext operation.
template <class Machine>
void TargetX86Base<Machine>::eliminateNextVectorSextInstruction(
Variable *SignExtendedResult) {
@@ -4721,10 +4722,10 @@
}
}
-// Turn an i64 Phi instruction into a pair of i32 Phi instructions, to
-// preserve integrity of liveness analysis. Undef values are also
-// turned into zeroes, since loOperand() and hiOperand() don't expect
-// Undef input.
+/// Turn an i64 Phi instruction into a pair of i32 Phi instructions, to
+/// preserve integrity of liveness analysis. Undef values are also
+/// turned into zeroes, since loOperand() and hiOperand() don't expect
+/// Undef input.
template <class Machine> void TargetX86Base<Machine>::prelowerPhis() {
// Pause constant blinding or pooling, blinding or pooling will be done later
// during phi lowering assignments
@@ -4770,8 +4771,8 @@
return true;
}
-// Lower the pre-ordered list of assignments into mov instructions.
-// Also has to do some ad-hoc register allocation as necessary.
+/// Lower the pre-ordered list of assignments into mov instructions.
+/// Also has to do some ad-hoc register allocation as necessary.
template <class Machine>
void TargetX86Base<Machine>::lowerPhiAssignments(
CfgNode *Node, const AssignList &Assignments) {
@@ -4975,12 +4976,12 @@
}
}
-// Construct a mask in a register that can be and'ed with a
-// floating-point value to mask off its sign bit. The value will be
-// <4 x 0x7fffffff> for f32 and v4f32, and <2 x 0x7fffffffffffffff>
-// for f64. Construct it as vector of ones logically right shifted
-// one bit. TODO(stichnot): Fix the wala TODO above, to represent
-// vector constants in memory.
+/// Construct a mask in a register that can be and'ed with a
+/// floating-point value to mask off its sign bit. The value will be
+/// <4 x 0x7fffffff> for f32 and v4f32, and <2 x 0x7fffffffffffffff>
+/// for f64. Construct it as vector of ones logically right shifted
+/// one bit. TODO(stichnot): Fix the wala TODO above, to represent
+/// vector constants in memory.
template <class Machine>
Variable *TargetX86Base<Machine>::makeVectorOfFabsMask(Type Ty,
int32_t RegNum) {
@@ -5007,8 +5008,8 @@
return OperandX8632Mem::create(Func, Ty, Loc, ConstantOffset);
}
-// Helper for legalize() to emit the right code to lower an operand to a
-// register of the appropriate type.
+/// Helper for legalize() to emit the right code to lower an operand to a
+/// register of the appropriate type.
template <class Machine>
Variable *TargetX86Base<Machine>::copyToReg(Operand *Src, int32_t RegNum) {
Type Ty = Src->getType();
@@ -5135,18 +5136,18 @@
return From;
}
-// Provide a trivial wrapper to legalize() for this common usage.
+/// Provide a trivial wrapper to legalize() for this common usage.
template <class Machine>
Variable *TargetX86Base<Machine>::legalizeToVar(Operand *From, int32_t RegNum) {
return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum));
}
-// For the cmp instruction, if Src1 is an immediate, or known to be a
-// physical register, we can allow Src0 to be a memory operand.
-// Otherwise, Src0 must be copied into a physical register.
-// (Actually, either Src0 or Src1 can be chosen for the physical
-// register, but unfortunately we have to commit to one or the other
-// before register allocation.)
+/// For the cmp instruction, if Src1 is an immediate, or known to be a
+/// physical register, we can allow Src0 to be a memory operand.
+/// Otherwise, Src0 must be copied into a physical register.
+/// (Actually, either Src0 or Src1 can be chosen for the physical
+/// register, but unfortunately we have to commit to one or the other
+/// before register allocation.)
template <class Machine>
Operand *TargetX86Base<Machine>::legalizeSrc0ForCmp(Operand *Src0,
Operand *Src1) {
@@ -5315,7 +5316,7 @@
llvm::report_fatal_error("undef value encountered by emitter.");
}
-// Randomize or pool an Immediate.
+/// Randomize or pool an Immediate.
template <class Machine>
Operand *TargetX86Base<Machine>::randomizeOrPoolImmediate(Constant *Immediate,
int32_t RegNum) {
diff --git a/src/IceThreading.cpp b/src/IceThreading.cpp
index 9720f77..153abff 100644
--- a/src/IceThreading.cpp
+++ b/src/IceThreading.cpp
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines threading-related functions.
-//
+///
+/// \file
+/// This file defines threading-related functions.
+///
//===----------------------------------------------------------------------===//
#include "IceThreading.h"
diff --git a/src/IceThreading.h b/src/IceThreading.h
index 4f04935..f59f46e 100644
--- a/src/IceThreading.h
+++ b/src/IceThreading.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares threading-related functions.
-//
+///
+/// \file
+/// This file declares threading-related functions.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICETHREADING_H
@@ -21,31 +22,31 @@
namespace Ice {
-// BoundedProducerConsumerQueue is a work queue that allows multiple
-// producers and multiple consumers. A producer adds entries using
-// blockingPush(), and may block if the queue is "full". A producer
-// uses notifyEnd() to indicate that no more entries will be added. A
-// consumer removes an item using blockingPop(), which will return
-// nullptr if notifyEnd() has been called and the queue is empty (it
-// never returns nullptr if the queue contained any items).
-//
-// The MaxSize ctor arg controls the maximum size the queue can grow
-// to (subject to a hard limit of MaxStaticSize-1). The Sequential
-// arg indicates purely sequential execution in which the single
-// thread should never wait().
-//
-// Two condition variables are used in the implementation.
-// GrewOrEnded signals a waiting worker that a producer has changed
-// the state of the queue. Shrunk signals a blocked producer that a
-// consumer has changed the state of the queue.
-//
-// The methods begin with Sequential-specific code to be most clear.
-// The lock and condition variables are not used in the Sequential
-// case.
-//
-// Internally, the queue is implemented as a circular array of size
-// MaxStaticSize, where the queue boundaries are denoted by the Front
-// and Back fields. Front==Back indicates an empty queue.
+/// BoundedProducerConsumerQueue is a work queue that allows multiple
+/// producers and multiple consumers. A producer adds entries using
+/// blockingPush(), and may block if the queue is "full". A producer
+/// uses notifyEnd() to indicate that no more entries will be added. A
+/// consumer removes an item using blockingPop(), which will return
+/// nullptr if notifyEnd() has been called and the queue is empty (it
+/// never returns nullptr if the queue contained any items).
+///
+/// The MaxSize ctor arg controls the maximum size the queue can grow
+/// to (subject to a hard limit of MaxStaticSize-1). The Sequential
+/// arg indicates purely sequential execution in which the single
+/// thread should never wait().
+///
+/// Two condition variables are used in the implementation.
+/// GrewOrEnded signals a waiting worker that a producer has changed
+/// the state of the queue. Shrunk signals a blocked producer that a
+/// consumer has changed the state of the queue.
+///
+/// The methods begin with Sequential-specific code to be most clear.
+/// The lock and condition variables are not used in the Sequential
+/// case.
+///
+/// Internally, the queue is implemented as a circular array of size
+/// MaxStaticSize, where the queue boundaries are denoted by the Front
+/// and Back fields. Front==Back indicates an empty queue.
template <typename T, size_t MaxStaticSize = 128>
class BoundedProducerConsumerQueue {
BoundedProducerConsumerQueue() = delete;
@@ -94,47 +95,47 @@
static_assert(!(MaxStaticSize & (MaxStaticSize - 1)),
"MaxStaticSize must be a power of 2");
- // WorkItems and Lock are read/written by all.
ICE_CACHELINE_BOUNDARY;
+ /// WorkItems and Lock are read/written by all.
T *WorkItems[MaxStaticSize];
ICE_CACHELINE_BOUNDARY;
- // Lock guards access to WorkItems, Front, Back, and IsEnded.
+ /// Lock guards access to WorkItems, Front, Back, and IsEnded.
GlobalLockType Lock;
ICE_CACHELINE_BOUNDARY;
- // GrewOrEnded is written by the producers and read by the
- // consumers. It is notified (by the producer) when something is
- // added to the queue, in case consumers are waiting for a non-empty
- // queue.
+ /// GrewOrEnded is written by the producers and read by the
+ /// consumers. It is notified (by the producer) when something is
+ /// added to the queue, in case consumers are waiting for a non-empty
+ /// queue.
std::condition_variable GrewOrEnded;
- // Back is the index into WorkItems[] of where the next element will
- // be pushed. (More precisely, Back&MaxStaticSize is the index.)
- // It is written by the producers, and read by all via size() and
- // empty().
+ /// Back is the index into WorkItems[] of where the next element will
+ /// be pushed. (More precisely, Back&MaxStaticSize is the index.)
+ /// It is written by the producers, and read by all via size() and
+ /// empty().
size_t Back = 0;
ICE_CACHELINE_BOUNDARY;
- // Shrunk is notified (by the consumer) when something is removed
- // from the queue, in case a producer is waiting for the queue to
- // drop below maximum capacity. It is written by the consumers and
- // read by the producers.
+ /// Shrunk is notified (by the consumer) when something is removed
+ /// from the queue, in case a producer is waiting for the queue to
+ /// drop below maximum capacity. It is written by the consumers and
+ /// read by the producers.
std::condition_variable Shrunk;
- // Front is the index into WorkItems[] of the oldest element,
- // i.e. the next to be popped. (More precisely Front&MaxStaticSize
- // is the index.) It is written by the consumers, and read by all
- // via size() and empty().
+ /// Front is the index into WorkItems[] of the oldest element,
+ /// i.e. the next to be popped. (More precisely Front&MaxStaticSize
+ /// is the index.) It is written by the consumers, and read by all
+ /// via size() and empty().
size_t Front = 0;
ICE_CACHELINE_BOUNDARY;
- // MaxSize and Sequential are read by all and written by none.
+ /// MaxSize and Sequential are read by all and written by none.
const size_t MaxSize;
const bool Sequential;
- // IsEnded is read by the consumers, and only written once by the
- // producer.
+ /// IsEnded is read by the consumers, and only written once by the
+ /// producer.
bool IsEnded = false;
- // The lock must be held when the following methods are called.
+ /// The lock must be held when the following methods are called.
bool empty() const { return Front == Back; }
size_t size() const { return Back - Front; }
void push(T *Item) {
@@ -147,45 +148,45 @@
}
};
-// EmitterWorkItem is a simple wrapper around a pointer that
-// represents a work item to be emitted, i.e. a function or a set of
-// global declarations and initializers, and it includes a sequence
-// number so that work items can be emitted in a particular order for
-// deterministic output. It acts like an interface class, but instead
-// of making the classes of interest inherit from EmitterWorkItem, it
-// wraps pointers to these classes. Some space is wasted compared to
-// storing the pointers in a union, but not too much due to the work
-// granularity.
+/// EmitterWorkItem is a simple wrapper around a pointer that
+/// represents a work item to be emitted, i.e. a function or a set of
+/// global declarations and initializers, and it includes a sequence
+/// number so that work items can be emitted in a particular order for
+/// deterministic output. It acts like an interface class, but instead
+/// of making the classes of interest inherit from EmitterWorkItem, it
+/// wraps pointers to these classes. Some space is wasted compared to
+/// storing the pointers in a union, but not too much due to the work
+/// granularity.
class EmitterWorkItem {
EmitterWorkItem() = delete;
EmitterWorkItem(const EmitterWorkItem &) = delete;
EmitterWorkItem &operator=(const EmitterWorkItem &) = delete;
public:
- // ItemKind can be one of the following:
- //
- // WI_Nop: No actual work. This is a placeholder to maintain
- // sequence numbers in case there is a translation error.
- //
- // WI_GlobalInits: A list of global declarations and initializers.
- //
- // WI_Asm: A function that has already had emitIAS() called on it.
- // The work is transferred via the Assembler buffer, and the
- // originating Cfg has been deleted (to recover lots of memory).
- //
- // WI_Cfg: A Cfg that has not yet had emit() or emitIAS() called on
- // it. This is only used as a debugging configuration when we want
- // to emit "readable" assembly code, possibly annotated with
- // liveness and other information only available in the Cfg and not
- // in the Assembler buffer.
+ /// ItemKind can be one of the following:
+ ///
+ /// WI_Nop: No actual work. This is a placeholder to maintain
+ /// sequence numbers in case there is a translation error.
+ ///
+ /// WI_GlobalInits: A list of global declarations and initializers.
+ ///
+ /// WI_Asm: A function that has already had emitIAS() called on it.
+ /// The work is transferred via the Assembler buffer, and the
+ /// originating Cfg has been deleted (to recover lots of memory).
+ ///
+ /// WI_Cfg: A Cfg that has not yet had emit() or emitIAS() called on
+ /// it. This is only used as a debugging configuration when we want
+ /// to emit "readable" assembly code, possibly annotated with
+ /// liveness and other information only available in the Cfg and not
+ /// in the Assembler buffer.
enum ItemKind { WI_Nop, WI_GlobalInits, WI_Asm, WI_Cfg };
- // Constructor for a WI_Nop work item.
+ /// Constructor for a WI_Nop work item.
explicit EmitterWorkItem(uint32_t Seq);
- // Constructor for a WI_GlobalInits work item.
+ /// Constructor for a WI_GlobalInits work item.
EmitterWorkItem(uint32_t Seq, VariableDeclarationList *D);
- // Constructor for a WI_Asm work item.
+ /// Constructor for a WI_Asm work item.
EmitterWorkItem(uint32_t Seq, Assembler *A);
- // Constructor for a WI_Cfg work item.
+ /// Constructor for a WI_Cfg work item.
EmitterWorkItem(uint32_t Seq, Cfg *F);
uint32_t getSequenceNumber() const { return Sequence; }
ItemKind getKind() const { return Kind; }
diff --git a/src/IceTimerTree.cpp b/src/IceTimerTree.cpp
index 879f06e..818efc3 100644
--- a/src/IceTimerTree.cpp
+++ b/src/IceTimerTree.cpp
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the TimerTree class, which tracks flat and
-// cumulative execution time collection of call chains.
-//
+///
+/// \file
+/// This file defines the TimerTree class, which tracks flat and
+/// cumulative execution time collection of call chains.
+///
//===----------------------------------------------------------------------===//
#include "IceTimerTree.h"
diff --git a/src/IceTimerTree.h b/src/IceTimerTree.h
index dd8dcf1..aabeb29 100644
--- a/src/IceTimerTree.h
+++ b/src/IceTimerTree.h
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the TimerTree class, which allows flat and
-// cumulative execution time collection of call chains.
-//
+///
+/// \file
+/// This file declares the TimerTree class, which allows flat and
+/// cumulative execution time collection of call chains.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICETIMERTREE_H
@@ -25,23 +26,23 @@
TimerStack() = delete;
TimerStack &operator=(const TimerStack &) = delete;
- // Timer tree index type. A variable of this type is used to access
- // an interior, not-necessarily-leaf node of the tree.
+ /// Timer tree index type. A variable of this type is used to access
+ /// an interior, not-necessarily-leaf node of the tree.
typedef std::vector<class TimerTreeNode>::size_type TTindex;
- // Representation of a path of leaf values leading to a particular
- // node. The representation happens to be in "reverse" order,
- // i.e. from leaf/interior to root, for implementation efficiency.
+ /// Representation of a path of leaf values leading to a particular
+ /// node. The representation happens to be in "reverse" order,
+ /// i.e. from leaf/interior to root, for implementation efficiency.
typedef llvm::SmallVector<TTindex, 8> PathType;
- // Representation of a mapping of leaf node indexes from one timer
- // stack to another.
+ /// Representation of a mapping of leaf node indexes from one timer
+ /// stack to another.
typedef std::vector<TimerIdT> TranslationType;
- // TimerTreeNode represents an interior or leaf node in the call tree.
- // It contains a list of children, a pointer to its parent, and the
- // timer ID for the node. It also holds the cumulative time spent at
- // this node and below. The children are always at a higher index in
- // the TimerTreeNode::Nodes array, and the parent is always at a lower
- // index.
+ /// TimerTreeNode represents an interior or leaf node in the call tree.
+ /// It contains a list of children, a pointer to its parent, and the
+ /// timer ID for the node. It also holds the cumulative time spent at
+ /// this node and below. The children are always at a higher index in
+ /// the TimerTreeNode::Nodes array, and the parent is always at a lower
+ /// index.
class TimerTreeNode {
TimerTreeNode &operator=(const TimerTreeNode &) = delete;
@@ -84,12 +85,12 @@
double FirstTimestamp;
double LastTimestamp;
uint64_t StateChangeCount = 0;
- // IDsIndex maps a symbolic timer name to its integer ID.
+ /// IDsIndex maps a symbolic timer name to its integer ID.
std::map<IceString, TimerIdT> IDsIndex;
- std::vector<IceString> IDs; // indexed by TimerIdT
- std::vector<TimerTreeNode> Nodes; // indexed by TTindex
- std::vector<double> LeafTimes; // indexed by TimerIdT
- std::vector<size_t> LeafCounts; // indexed by TimerIdT
+ std::vector<IceString> IDs; /// indexed by TimerIdT
+ std::vector<TimerTreeNode> Nodes; /// indexed by TTindex
+ std::vector<double> LeafTimes; /// indexed by TimerIdT
+ std::vector<size_t> LeafCounts; /// indexed by TimerIdT
TTindex StackTop = 0;
};
diff --git a/src/IceTranslator.cpp b/src/IceTranslator.cpp
index a00fd6b..a2db1a2 100644
--- a/src/IceTranslator.cpp
+++ b/src/IceTranslator.cpp
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the general driver class for translating ICE to
-// machine code.
-//
+///
+/// \file
+/// This file defines the general driver class for translating ICE to
+/// machine code.
+///
//===----------------------------------------------------------------------===//
#include "IceTranslator.h"
diff --git a/src/IceTranslator.h b/src/IceTranslator.h
index 29b2d77..9fe46ee 100644
--- a/src/IceTranslator.h
+++ b/src/IceTranslator.h
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the general driver class for translating ICE to
-// machine code.
-//
+///
+/// \file
+/// This file declares the general driver class for translating ICE to
+/// machine code.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICETRANSLATOR_H
@@ -29,9 +30,9 @@
class VariableDeclaration;
class GlobalContext;
-// Base class for translating ICE to machine code. Derived classes convert
-// other intermediate representations down to ICE, and then call the appropriate
-// (inherited) methods to convert ICE into machine instructions.
+/// Base class for translating ICE to machine code. Derived classes convert
+/// other intermediate representations down to ICE, and then call the
+/// appropriate (inherited) methods to convert ICE into machine instructions.
class Translator {
Translator() = delete;
Translator(const Translator &) = delete;
@@ -70,7 +71,7 @@
protected:
GlobalContext *Ctx;
uint32_t NextSequenceNumber;
- // ErrorCode of the translation.
+ /// ErrorCode of the translation.
ErrorCode ErrorStatus;
};
diff --git a/src/IceTypeConverter.cpp b/src/IceTypeConverter.cpp
index 4341dcb..ec9e37b 100644
--- a/src/IceTypeConverter.cpp
+++ b/src/IceTypeConverter.cpp
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements how to convert LLVM types to ICE types, and ICE types
-// to LLVM types.
-//
+///
+/// \file
+/// This file implements how to convert LLVM types to ICE types, and ICE types
+/// to LLVM types.
+///
//===----------------------------------------------------------------------===//
#include "IceTypeConverter.h"
diff --git a/src/IceTypeConverter.h b/src/IceTypeConverter.h
index 18e3e00..81dde92 100644
--- a/src/IceTypeConverter.h
+++ b/src/IceTypeConverter.h
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines how to convert LLVM types to ICE types, and ICE types
-// to LLVM types.
-//
+///
+/// \file
+/// This file defines how to convert LLVM types to ICE types, and ICE types
+/// to LLVM types.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICETYPECONVERTER_H
@@ -45,13 +46,13 @@
}
private:
- // The mapping from LLVM types to corresopnding Ice types.
+ /// The mapping from LLVM types to corresopnding Ice types.
std::map<llvm::Type *, Type> LLVM2IceMap;
- // Add LLVM/ICE pair to internal tables.
+ /// Add LLVM/ICE pair to internal tables.
void addLLVMType(Type Ty, llvm::Type *LLVMTy);
- // Converts types not in LLVM2IceMap.
+ /// Converts types not in LLVM2IceMap.
Type convertToIceTypeOther(llvm::Type *LLVMTy) const;
};
diff --git a/src/IceTypes.cpp b/src/IceTypes.cpp
index 1b0ffb3..2099cb9 100644
--- a/src/IceTypes.cpp
+++ b/src/IceTypes.cpp
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines a few attributes of Subzero primitive types.
-//
+///
+/// \file
+/// This file defines a few attributes of Subzero primitive types.
+///
//===----------------------------------------------------------------------===//
#include "IceTypes.h"
diff --git a/src/IceTypes.h b/src/IceTypes.h
index 7daa8a7..1430094 100644
--- a/src/IceTypes.h
+++ b/src/IceTypes.h
@@ -6,11 +6,12 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares a few properties of the primitive types allowed
-// in Subzero. Every Subzero source file is expected to include
-// IceTypes.h.
-//
+///
+/// \file
+/// This file declares a few properties of the primitive types allowed
+/// in Subzero. Every Subzero source file is expected to include
+/// IceTypes.h.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICETYPES_H
@@ -41,8 +42,8 @@
return Stream << targetArchString(Arch);
}
-// The list of all target instruction sets. Individual targets will
-// map this to include only what is valid for the target.
+/// The list of all target instruction sets. Individual targets will
+/// map this to include only what is valid for the target.
enum TargetInstructionSet {
// Represents baseline that can be assumed for a target (usually "Begin").
BaseInstructionSet,
@@ -88,28 +89,28 @@
/// Returns the number of bits in a scalar integer type.
SizeT getScalarIntBitWidth(Type Ty);
-// Check if a type is byte sized (slight optimization over typeWidthInBytes).
+/// Check if a type is byte sized (slight optimization over typeWidthInBytes).
inline bool isByteSizedType(Type Ty) {
bool result = Ty == IceType_i8 || Ty == IceType_i1;
assert(result == (1 == typeWidthInBytes(Ty)));
return result;
}
-// Check if Ty is byte sized and specifically i8. Assert that it's not
-// byte sized due to being an i1.
+/// Check if Ty is byte sized and specifically i8. Assert that it's not
+/// byte sized due to being an i1.
inline bool isByteSizedArithType(Type Ty) {
assert(Ty != IceType_i1);
return Ty == IceType_i8;
}
-// Return true if Ty is i32. This asserts that Ty is either i32 or i64.
+/// Return true if Ty is i32. This asserts that Ty is either i32 or i64.
inline bool isInt32Asserting32Or64(Type Ty) {
bool result = Ty == IceType_i32;
assert(result || Ty == IceType_i64);
return result;
}
-// Return true if Ty is f32. This asserts that Ty is either f32 or f64.
+/// Return true if Ty is f32. This asserts that Ty is either f32 or f64.
inline bool isFloat32Asserting32Or64(Type Ty) {
bool result = Ty == IceType_f32;
assert(result || Ty == IceType_f64);
@@ -129,8 +130,8 @@
public:
typedef std::vector<Type> ArgListType;
- // Creates a function signature type with the given return type.
- // Parameter types should be added using calls to appendArgType.
+ /// Creates a function signature type with the given return type.
+ /// Parameter types should be added using calls to appendArgType.
FuncSigType() = default;
FuncSigType(const FuncSigType &Ty) = default;
@@ -147,9 +148,9 @@
void dump(Ostream &Stream) const;
private:
- // The return type.
+ /// The return type.
Type ReturnType = IceType_void;
- // The list of parameters.
+ /// The list of parameters.
ArgListType ArgList;
};
diff --git a/src/IceUtils.h b/src/IceUtils.h
index 6b0d729..6d65ade 100644
--- a/src/IceUtils.h
+++ b/src/IceUtils.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares some utility functions.
-//
+///
+/// \file
+/// This file declares some utility functions.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEUTILS_H
@@ -18,11 +19,11 @@
namespace Ice {
-// Similar to bit_cast, but allows copying from types of unrelated
-// sizes. This method was introduced to enable the strict aliasing
-// optimizations of GCC 4.4. Basically, GCC mindlessly relies on
-// obscure details in the C++ standard that make reinterpret_cast
-// virtually useless.
+/// Similar to bit_cast, but allows copying from types of unrelated
+/// sizes. This method was introduced to enable the strict aliasing
+/// optimizations of GCC 4.4. Basically, GCC mindlessly relies on
+/// obscure details in the C++ standard that make reinterpret_cast
+/// virtually useless.
template <class D, class S> inline D bit_copy(const S &source) {
D destination;
// This use of memcpy is safe: source and destination cannot overlap.
@@ -37,7 +38,7 @@
Utils &operator=(const Utils &) = delete;
public:
- // Check whether an N-bit two's-complement representation can hold value.
+ /// Check whether an N-bit two's-complement representation can hold value.
template <typename T> static inline bool IsInt(int N, T value) {
assert((0 < N) &&
(static_cast<unsigned int>(N) < (CHAR_BIT * sizeof(value))));
@@ -52,8 +53,8 @@
return (0 <= value) && (value < limit);
}
- // Check whether the magnitude of value fits in N bits, i.e., whether an
- // (N+1)-bit sign-magnitude representation can hold value.
+ /// Check whether the magnitude of value fits in N bits, i.e., whether an
+ /// (N+1)-bit sign-magnitude representation can hold value.
template <typename T> static inline bool IsAbsoluteUint(int N, T Value) {
assert((0 < N) &&
(static_cast<unsigned int>(N) < (CHAR_BIT * sizeof(Value))));
@@ -62,27 +63,27 @@
return IsUint(N, Value);
}
- // Return true if the addition X + Y will cause integer overflow for
- // integers of type T.
+ /// Return true if the addition X + Y will cause integer overflow for
+ /// integers of type T.
template <typename T> static inline bool WouldOverflowAdd(T X, T Y) {
return ((X > 0 && Y > 0 && (X > std::numeric_limits<T>::max() - Y)) ||
(X < 0 && Y < 0 && (X < std::numeric_limits<T>::min() - Y)));
}
- // Return true if X is already aligned by N, where N is a power of 2.
+ /// Return true if X is already aligned by N, where N is a power of 2.
template <typename T> static inline bool IsAligned(T X, intptr_t N) {
assert(llvm::isPowerOf2_64(N));
return (X & (N - 1)) == 0;
}
- // Return Value adjusted to the next highest multiple of Alignment.
+ /// Return Value adjusted to the next highest multiple of Alignment.
static inline uint32_t applyAlignment(uint32_t Value, uint32_t Alignment) {
assert(llvm::isPowerOf2_32(Alignment));
return (Value + Alignment - 1) & -Alignment;
}
- // Return amount which must be added to adjust Pos to the next highest
- // multiple of Align.
+ /// Return amount which must be added to adjust Pos to the next highest
+ /// multiple of Align.
static inline uint64_t OffsetToAlignment(uint64_t Pos, uint64_t Align) {
assert(llvm::isPowerOf2_64(Align));
uint64_t Mod = Pos & (Align - 1);
@@ -91,15 +92,15 @@
return Align - Mod;
}
- // Rotate the value bit pattern to the left by shift bits.
- // Precondition: 0 <= shift < 32
+ /// Rotate the value bit pattern to the left by shift bits.
+ /// Precondition: 0 <= shift < 32
static inline uint32_t rotateLeft32(uint32_t value, uint32_t shift) {
if (shift == 0)
return value;
return (value << shift) | (value >> (32 - shift));
}
- // Rotate the value bit pattern to the right by shift bits.
+ /// Rotate the value bit pattern to the right by shift bits.
static inline uint32_t rotateRight32(uint32_t value, uint32_t shift) {
if (shift == 0)
return value;
diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp
index fea11d0..11e0b8e 100644
--- a/src/PNaClTranslator.cpp
+++ b/src/PNaClTranslator.cpp
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the PNaCl bitcode file to Ice, to machine code
-// translator.
-//
+///
+/// \file
+/// This file implements the PNaCl bitcode file to Ice, to machine code
+/// translator.
+///
//===----------------------------------------------------------------------===//
#include "PNaClTranslator.h"
diff --git a/src/PNaClTranslator.h b/src/PNaClTranslator.h
index b8764a6..b6286e8 100644
--- a/src/PNaClTranslator.h
+++ b/src/PNaClTranslator.h
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file declares the PNaCl bitcode file to ICE, to machine code
-// translator.
-//
+///
+/// \file
+/// This file declares the PNaCl bitcode file to ICE, to machine code
+/// translator.
+///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_PNACLTRANSLATOR_H
@@ -34,13 +35,13 @@
public:
explicit PNaClTranslator(GlobalContext *Ctx) : Translator(Ctx) {}
- // Reads the PNaCl bitcode file and translates to ICE, which is then
- // converted to machine code. Sets ErrorStatus to 1 if any errors
- // occurred. Takes ownership of the MemoryObject.
+ /// Reads the PNaCl bitcode file and translates to ICE, which is then
+ /// converted to machine code. Sets ErrorStatus to 1 if any errors
+ /// occurred. Takes ownership of the MemoryObject.
void translate(const std::string &IRFilename,
std::unique_ptr<llvm::MemoryObject> &&MemoryObject);
- // Reads MemBuf, assuming it is the PNaCl bitcode contents of IRFilename.
+ /// Reads MemBuf, assuming it is the PNaCl bitcode contents of IRFilename.
void translateBuffer(const std::string &IRFilename,
llvm::MemoryBuffer *MemBuf);
};
diff --git a/src/main.cpp b/src/main.cpp
index c5ee1e4..a6cb490 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the entry point for translating PNaCl bitcode into
-// native code.
-//
+///
+/// \file
+/// This file defines the entry point for translating PNaCl bitcode into
+/// native code.
+///
//===----------------------------------------------------------------------===//
#include "IceBrowserCompileServer.h"