<commit_before>/*
* Copyright (C) 2008-2012 J-P Nurmi <jpnurmi@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*/

#include "sessiontreeitem.h"
#include "sessiontreewidget.h"

SessionTreeItem::SessionTreeItem(Session* session, QTreeWidget* parent) : QTreeWidgetItem(parent)
{
    d.session = session;
    d.alerted = false;
    d.inactive = true;
    d.highlighted = false;
}

SessionTreeItem::SessionTreeItem(Session* session, QTreeWidgetItem* parent) : QTreeWidgetItem(parent)
{
    d.session = session;
    d.alerted = false;
    d.inactive = false;
    d.highlighted = false;
}

Session* SessionTreeItem::session() const
{
    return d.session;
}

SessionTreeItem* SessionTreeItem::findChild(const QString& name) const
{
    for (int i = 0; i < childCount(); ++i)
        if (child(i)->text(0).compare(name, Qt::CaseInsensitive) == 0)
            return static_cast<SessionTreeItem*>(child(i));
    return 0;
}

QVariant SessionTreeItem::data(int column, int role) const
{
    if (role == Qt::ForegroundRole)
    {
        SessionTreeWidget* tw = static_cast<SessionTreeWidget*>(treeWidget());
        if (d.inactive)
            return tw->statusColor(SessionTreeWidget::Inactive);
        if (d.alerted)
            return tw->statusColor(SessionTreeWidget::Alert);
        if (d.highlighted)
            return tw->statusColor(SessionTreeWidget::Highlight);
        return tw->statusColor(SessionTreeWidget::Active);
    }
    return QTreeWidgetItem::data(column, role);
}

void SessionTreeItem::setAlerted(bool alerted)
{
    d.alerted = alerted;
    emitDataChanged();
}

void SessionTreeItem::setInactive(bool inactive)
{
    d.inactive = inactive;
    emitDataChanged();
}

void SessionTreeItem::setHighlighted(bool highlighted)
{
    d.highlighted = highlighted;
    emitDataChanged();
}
<commit_msg>SessionTreeItem::setXxx(): avoid unnecessary dataChanged() emits<commit_after>/*
* Copyright (C) 2008-2012 J-P Nurmi <jpnurmi@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*/

#include "sessiontreeitem.h"
#include "sessiontreewidget.h"

SessionTreeItem::SessionTreeItem(Session* session, QTreeWidget* parent) : QTreeWidgetItem(parent)
{
    d.session = session;
    d.alerted = false;
    d.inactive = true;
    d.highlighted = false;
}

SessionTreeItem::SessionTreeItem(Session* session, QTreeWidgetItem* parent) : QTreeWidgetItem(parent)
{
    d.session = session;
    d.alerted = false;
    d.inactive = false;
    d.highlighted = false;
}

Session* SessionTreeItem::session() const
{
    return d.session;
}

SessionTreeItem* SessionTreeItem::findChild(const QString& name) const
{
    for (int i = 0; i < childCount(); ++i)
        if (child(i)->text(0).compare(name, Qt::CaseInsensitive) == 0)
            return static_cast<SessionTreeItem*>(child(i));
    return 0;
}

QVariant SessionTreeItem::data(int column, int role) const
{
    if (role == Qt::ForegroundRole)
    {
        SessionTreeWidget* tw = static_cast<SessionTreeWidget*>(treeWidget());
        if (d.inactive)
            return tw->statusColor(SessionTreeWidget::Inactive);
        if (d.alerted)
            return tw->statusColor(SessionTreeWidget::Alert);
        if (d.highlighted)
            return tw->statusColor(SessionTreeWidget::Highlight);
        return tw->statusColor(SessionTreeWidget::Active);
    }
    return QTreeWidgetItem::data(column, role);
}

void SessionTreeItem::setAlerted(bool alerted)
{
    if (d.alerted != alerted)
    {
        d.alerted = alerted;
        emitDataChanged();
    }
}

void SessionTreeItem::setInactive(bool inactive)
{
    if (d.inactive != inactive)
    {
        d.inactive = inactive;
        emitDataChanged();
    }
}

void SessionTreeItem::setHighlighted(bool highlighted)
{
    if (d.highlighted != highlighted)
    {
        d.highlighted = highlighted;
        emitDataChanged();
    }
}
<|endoftext|>


<commit_before>/*
 * This program is a Proof of Concept for enhancement of Futures in order to:
 * - support Future dependencies (callbacks)
 * - support Futures grouping
 *
 * The constraints:
 * - limit extra code
 * - limit extra time
 * - support both Future and FakeFuture
 * - compatibility with current usage of futures
 *
 * It just uses an Arduino UNO with USB console.
 */

// Possible ways for callbacks:
// - one or more listener ABC with virtual method(s) for various future changes
//		- provided at construction time (additional args with default nullptr)
//	+ easy to implement
//	- virtual overhead of code size and speed (particularly from inside ISR)
// - one functor on all Future and FakeFuture templates
//		- default functor type (empty)
//		- default arg value
//	+ impact size/speed only when not empty and to the strict minimum
//	- much harder to implement properly

#include <fastarduino/future.h>
#include <fastarduino/initializer_list.h>

#include <fastarduino/time.h>
#include <fastarduino/uart.h>
#include <fastarduino/iomanip.h>
#include <fastarduino/flash.h>
#include <fastarduino/array.h>

#include <fastarduino/tests/assertions.h>

// Register vector for UART (used for debug)
REGISTER_UATX_ISR(0)

// #define REAL_FUTURE

// Example starts here
//=====================

using namespace future;
using namespace streams;
using namespace containers;

static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 128;
static char output_buffer[OUTPUT_BUFFER_SIZE];

//TODO - make on_change...() private and check if OK
//TODO - perform checks on FuturesGroup

// template<typename F, uint8_t SIZE> class FuturesGroup
// {
// 	//TODO ensure F is a proper future (need specific traits...)
// public:
// 	//TODO how to deal with move constructor?
// 	FutureStatus status() const
// 	{
// 		//TODO find status among all futures (or only last one?)
// 		return status_;
// 	}

// 	FutureStatus await() const
// 	{
// 		while (true)
// 		{
// 			FutureStatus temp_status = status();
// 			if (temp_status != FutureStatus::NOT_READY)
// 				return temp_status;
// 			time::yield();
// 		}
// 	}

// 	int error() const
// 	{
// 		return error_;
// 	}

// protected:
// 	FuturesGroup(std::initializer_list<F&> futures)
// 	{
// 		static_assert(
// 			futures.size() == SIZE, "FuturesGroup constructor must be initialized with exactly SIZE parameters");
// 		F** temp = futures_;
// 		for (F& future: futures)
// 			*temp++ = future;
// 	}
//
// private:
// 	F* futures_[SIZE];
// 	uint8_t count_ready_ = 0;
// };

#ifdef REAL_FUTURE
#define ABSTRACTFUTURE AbstractFuture
#define FUTURE Future
#else
#define ABSTRACTFUTURE AbstractFakeFuture
#define FUTURE FakeFuture
#endif

struct FutureListener : FutureStatusListener<ABSTRACTFUTURE>, FutureOutputListener<ABSTRACTFUTURE>
{
	explicit FutureListener(ostream& out) : out_{out} {}

	void on_status_change(UNUSED const ABSTRACTFUTURE& future, FutureStatus new_status) override
	{
		out_ << F("on_status_change() status = ") << new_status << endl;
	}
	void on_output_change(UNUSED const ABSTRACTFUTURE& future, uint8_t* output_data, uint8_t* output_current) override
	{
		out_	<< F("on_output_change() data = ") << hex << output_data << F(", current = ")
				<< hex << output_current << endl;
	}

	ostream& out_;
};

class MyFuture : public FUTURE<uint32_t, uint8_t>
{
	using PARENT = FUTURE<uint32_t, uint8_t>;
	static constexpr uint8_t REG_INDEX = 0x34;

public:
	MyFuture(FutureListener& listener) : PARENT{REG_INDEX, &listener, &listener} {}
	MyFuture(MyFuture&&) = default;
	MyFuture& operator=(MyFuture&&) = default;
};

struct UpdateRegister
{
	UpdateRegister(uint8_t reg_index)
	{
		data[0] = data[1] = reg_index;
	}

	uint8_t data[3] = {0 ,0, 0};
};
class UpdateRegisterFuture : public FUTURE<uint8_t, UpdateRegister>, public FutureOutputListener<ABSTRACTFUTURE>
{
	using PARENT = FUTURE<uint8_t, UpdateRegister>;

public:
	UpdateRegisterFuture(uint8_t reg_index, uint8_t set_mask)
		:	PARENT{UpdateRegister{reg_index}, nullptr, this}, set_mask_{set_mask} {}
	UpdateRegisterFuture(UpdateRegisterFuture&&) = default;
	UpdateRegisterFuture& operator=(UpdateRegisterFuture&&) = default;

	void on_output_change(
		UNUSED const ABSTRACTFUTURE& future, UNUSED uint8_t* output_data, uint8_t* output_current) override
	{
		// Only one call expected, directly get output value and change it
		uint8_t value = *(output_current - 1);
		value |= set_mask_;
		//TODO const_cast not good here, maybe overload Future get_input() to provide const and non-const flavours
		const_cast<UpdateRegister&>(get_input()).data[2] = value;
	}

private:
	uint8_t set_mask_;
};

int main() __attribute__((OS_main));
int main()
{
	board::init();
	// Enable interrupts at startup time
	sei();

	// Initialize debugging output
	serial::hard::UATX<board::USART::USART0> uart{output_buffer};
	uart.begin(115200);
	ostream out = uart.out();
	out << boolalpha << showbase;

	FutureListener listener{out};

	// Start feeding future and check output
	MyFuture f1{listener};
	out << F("set_future_value(0x11)") << endl;
	f1.set_future_value_(uint8_t(0x11));

	out << F("set_future_value(0x22)") << endl;
	f1.set_future_value_(uint8_t(0x22));

	out << F("set_future_value(0x33)") << endl;
	f1.set_future_value_(uint8_t(0x33));

	out << F("set_future_value(0x44)") << endl;
	f1.set_future_value_(uint8_t(0x44));

	out << F("f1.status() = ") << f1.status() << endl;
	uint32_t result = 0;
	out << F("f1.get(result) = ") << f1.get(result) << endl;
	out << F("result = ") << hex << result << endl;

	// Start feeding future, force error and check output
	MyFuture f2{listener};
	f2.set_future_value_(uint8_t(0x55));
	f2.set_future_finish_();
	f2.set_future_error_(-10);
	out << F("f2.status() = ") << f2.status() << endl;
	out << F("f2.error() = ") << dec << f2.error() << endl;

	UpdateRegisterFuture f3{0xF7, 0x12};
	uint8_t data = 0;
	out << F("f3.get_storage_value_(data) = ") << f3.get_storage_value_(data) << endl;
	out << F("data = ") << hex << data << endl;
	out << F("f3.set_future_value_(0x40) = ") << f3.set_future_value_(uint8_t(0x40)) << endl;
	out << F("f3.get_storage_value_(data) = ") << f3.get_storage_value_(data) << endl;
	out << F("data = ") << hex << data << endl;
	out << F("f3.get_storage_value_(data) = ") << f3.get_storage_value_(data) << endl;
	out << F("data = ") << hex << data << endl;
	out << F("f3.status() = ") << f3.status() << endl;
}
<commit_msg>Update comments.<commit_after>/*
 * This program is a Proof of Concept for enhancement of Futures in order to:
 * - support Future dependencies (callbacks)
 * - support Futures grouping
 *
 * The constraints:
 * - limit extra code
 * - limit extra time
 * - support both Future and FakeFuture
 * - compatibility with current usage of futures
 *
 * It just uses an Arduino UNO with USB console.
 */

// Possible ways for callbacks:
// - one or more listener ABC with virtual method(s) for various future changes
//		- provided at construction time (additional args with default nullptr)
//	+ easy to implement
//	- virtual overhead of code size and speed (particularly from inside ISR)
// - one functor on all Future and FakeFuture templates
//		- default functor type (empty)
//		- default arg value
//	+ impact size/speed only when not empty and to the strict minimum
//	- much harder to implement properly

#include <fastarduino/future.h>
#include <fastarduino/initializer_list.h>

#include <fastarduino/time.h>
#include <fastarduino/uart.h>
#include <fastarduino/iomanip.h>
#include <fastarduino/flash.h>
#include <fastarduino/array.h>

#include <fastarduino/tests/assertions.h>

// Register vector for UART (used for debug)
REGISTER_UATX_ISR(0)

// #define REAL_FUTURE

// Example starts here
//=====================

using namespace future;
using namespace streams;
using namespace containers;

static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 128;
static char output_buffer[OUTPUT_BUFFER_SIZE];

//TODO - perform checks on FuturesGroup

// template<typename F, uint8_t SIZE> class FuturesGroup
// {
// 	//TODO ensure F is a proper future (need specific traits...)
// public:
// 	//TODO how to deal with move constructor?
// 	FutureStatus status() const
// 	{
// 		//TODO find status among all futures (or only last one?)
// 		return status_;
// 	}

// 	FutureStatus await() const
// 	{
// 		while (true)
// 		{
// 			FutureStatus temp_status = status();
// 			if (temp_status != FutureStatus::NOT_READY)
// 				return temp_status;
// 			time::yield();
// 		}
// 	}

// 	int error() const
// 	{
// 		return error_;
// 	}

// protected:
// 	FuturesGroup(std::initializer_list<F&> futures)
// 	{
// 		static_assert(
// 			futures.size() == SIZE, "FuturesGroup constructor must be initialized with exactly SIZE parameters");
// 		F** temp = futures_;
// 		for (F& future: futures)
// 			*temp++ = future;
// 	}
//
// private:
// 	F* futures_[SIZE];
// 	uint8_t count_ready_ = 0;
// };

#ifdef REAL_FUTURE
#define ABSTRACTFUTURE AbstractFuture
#define FUTURE Future
#else
#define ABSTRACTFUTURE AbstractFakeFuture
#define FUTURE FakeFuture
#endif

struct FutureListener : FutureStatusListener<ABSTRACTFUTURE>, FutureOutputListener<ABSTRACTFUTURE>
{
	explicit FutureListener(ostream& out) : out_{out} {}

	void on_status_change(UNUSED const ABSTRACTFUTURE& future, FutureStatus new_status) override
	{
		out_ << F("on_status_change() status = ") << new_status << endl;
	}
	void on_output_change(UNUSED const ABSTRACTFUTURE& future, uint8_t* output_data, uint8_t* output_current) override
	{
		out_	<< F("on_output_change() data = ") << hex << output_data << F(", current = ")
				<< hex << output_current << endl;
	}

	ostream& out_;
};

class MyFuture : public FUTURE<uint32_t, uint8_t>
{
	using PARENT = FUTURE<uint32_t, uint8_t>;
	static constexpr uint8_t REG_INDEX = 0x34;

public:
	MyFuture(FutureListener& listener) : PARENT{REG_INDEX, &listener, &listener} {}
	MyFuture(MyFuture&&) = default;
	MyFuture& operator=(MyFuture&&) = default;
};

struct UpdateRegister
{
	UpdateRegister(uint8_t reg_index)
	{
		data[0] = data[1] = reg_index;
	}

	uint8_t data[3] = {0 ,0, 0};
};
class UpdateRegisterFuture : public FUTURE<uint8_t, UpdateRegister>, public FutureOutputListener<ABSTRACTFUTURE>
{
	using PARENT = FUTURE<uint8_t, UpdateRegister>;

public:
	UpdateRegisterFuture(uint8_t reg_index, uint8_t set_mask)
		:	PARENT{UpdateRegister{reg_index}, nullptr, this}, set_mask_{set_mask} {}
	UpdateRegisterFuture(UpdateRegisterFuture&&) = default;
	UpdateRegisterFuture& operator=(UpdateRegisterFuture&&) = default;

private:
	void on_output_change(
		UNUSED const ABSTRACTFUTURE& future, UNUSED uint8_t* output_data, uint8_t* output_current) override
	{
		// Only one call expected, directly get output value and change it
		uint8_t value = *(output_current - 1);
		value |= set_mask_;
		//TODO const_cast not good here, maybe overload Future get_input() to provide const and non-const flavours
		const_cast<UpdateRegister&>(get_input()).data[2] = value;
	}

	uint8_t set_mask_;
};

int main() __attribute__((OS_main));
int main()
{
	board::init();
	// Enable interrupts at startup time
	sei();

	// Initialize debugging output
	serial::hard::UATX<board::USART::USART0> uart{output_buffer};
	uart.begin(115200);
	ostream out = uart.out();
	out << boolalpha << showbase;

	FutureListener listener{out};

	// Start feeding future and check output
	MyFuture f1{listener};
	out << F("set_future_value(0x11)") << endl;
	f1.set_future_value_(uint8_t(0x11));

	out << F("set_future_value(0x22)") << endl;
	f1.set_future_value_(uint8_t(0x22));

	out << F("set_future_value(0x33)") << endl;
	f1.set_future_value_(uint8_t(0x33));

	out << F("set_future_value(0x44)") << endl;
	f1.set_future_value_(uint8_t(0x44));

	out << F("f1.status() = ") << f1.status() << endl;
	uint32_t result = 0;
	out << F("f1.get(result) = ") << f1.get(result) << endl;
	out << F("result = ") << hex << result << endl;

	// Start feeding future, force error and check output
	MyFuture f2{listener};
	f2.set_future_value_(uint8_t(0x55));
	f2.set_future_finish_();
	f2.set_future_error_(-10);
	out << F("f2.status() = ") << f2.status() << endl;
	out << F("f2.error() = ") << dec << f2.error() << endl;

	UpdateRegisterFuture f3{0xF7, 0x12};
	uint8_t data = 0;
	out << F("f3.get_storage_value_(data) = ") << f3.get_storage_value_(data) << endl;
	out << F("data = ") << hex << data << endl;
	out << F("f3.set_future_value_(0x40) = ") << f3.set_future_value_(uint8_t(0x40)) << endl;
	out << F("f3.get_storage_value_(data) = ") << f3.get_storage_value_(data) << endl;
	out << F("data = ") << hex << data << endl;
	out << F("f3.get_storage_value_(data) = ") << f3.get_storage_value_(data) << endl;
	out << F("data = ") << hex << data << endl;
	out << F("f3.status() = ") << f3.status() << endl;
}
<|endoftext|>


<commit_before>//===- AsmWriterEmitter.cpp - Generate an assembly writer -----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend is emits an assembly printer for the current target.
// Note that this is currently fairly skeletal, but will grow over time.
//
//===----------------------------------------------------------------------===//

#include "AsmWriterEmitter.h"
#include "CodeGenTarget.h"
#include "Record.h"
#include <algorithm>
#include <ostream>
using namespace llvm;

static bool isIdentChar(char C) {
  return (C >= 'a' && C <= 'z') ||
         (C >= 'A' && C <= 'Z') ||
         (C >= '0' && C <= '9') ||
         C == '_';
}

namespace {
  struct AsmWriterOperand {
    enum { isLiteralTextOperand, isMachineInstrOperand } OperandType;

    /// Str - For isLiteralTextOperand, this IS the literal text.  For
    /// isMachineInstrOperand, this is the PrinterMethodName for the operand.
    std::string Str;

    /// MiOpNo - For isMachineInstrOperand, this is the operand number of the
    /// machine instruction.
    unsigned MIOpNo;

    /// OpVT - For isMachineInstrOperand, this is the value type for the
    /// operand.
    MVT::ValueType OpVT;

    AsmWriterOperand(const std::string &LitStr)
      : OperandType(isLiteralTextOperand),  Str(LitStr) {}

    AsmWriterOperand(const std::string &Printer, unsigned OpNo,
                     MVT::ValueType VT) : OperandType(isMachineInstrOperand),
                                          Str(Printer), MIOpNo(OpNo), OpVT(VT){}

    bool operator!=(const AsmWriterOperand &Other) const {
      if (OperandType != Other.OperandType || Str != Other.Str) return true;
      if (OperandType == isMachineInstrOperand)
        return MIOpNo != Other.MIOpNo || OpVT != Other.OpVT;
      return false;
    }
    bool operator==(const AsmWriterOperand &Other) const {
      return !operator!=(Other);
    }
    void EmitCode(std::ostream &OS) const;
  };

  struct AsmWriterInst {
    std::vector<AsmWriterOperand> Operands;
    const CodeGenInstruction *CGI;

    AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant);

    /// MatchesAllButOneOp - If this instruction is exactly identical to the
    /// specified instruction except for one differing operand, return the
    /// differing operand number.  Otherwise return ~0.
    unsigned MatchesAllButOneOp(const AsmWriterInst &Other) const;

  private:
    void AddLiteralString(const std::string &Str) {
      // If the last operand was already a literal text string, append this to
      // it, otherwise add a new operand.
      if (!Operands.empty() &&
          Operands.back().OperandType == AsmWriterOperand::isLiteralTextOperand)
        Operands.back().Str.append(Str);
      else
        Operands.push_back(AsmWriterOperand(Str));
    }
  };
}

void AsmWriterOperand::EmitCode(std::ostream &OS) const {
  if (OperandType == isLiteralTextOperand)
    OS << "O << \"" << Str << "\"; ";
  else
    OS << Str << "(MI, " << MIOpNo << ", MVT::" << getName(OpVT) << "); ";
}

/// ParseAsmString - Parse the specified Instruction's AsmString into this
/// AsmWriterInst.
///
AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) {
  this->CGI = &CGI;
  bool inVariant = false;  // True if we are inside a {.|.|.} region.

  const std::string &AsmString = CGI.AsmString;
  std::string::size_type LastEmitted = 0;
  while (LastEmitted != AsmString.size()) {
    std::string::size_type DollarPos =
      AsmString.find_first_of("${|}", LastEmitted);
    if (DollarPos == std::string::npos) DollarPos = AsmString.size();

    // Emit a constant string fragment.
    if (DollarPos != LastEmitted) {
      // TODO: this should eventually handle escaping.
      AddLiteralString(std::string(AsmString.begin()+LastEmitted,
                                   AsmString.begin()+DollarPos));
      LastEmitted = DollarPos;
    } else if (AsmString[DollarPos] == '{') {
      if (inVariant)
        throw "Nested variants found for instruction '" + CGI.Name + "'!";
      LastEmitted = DollarPos+1;
      inVariant = true;   // We are now inside of the variant!
      for (unsigned i = 0; i != Variant; ++i) {
        // Skip over all of the text for an irrelevant variant here.  The
        // next variant starts at |, or there may not be text for this
        // variant if we see a }.
        std::string::size_type NP =
          AsmString.find_first_of("|}", LastEmitted);
        if (NP == std::string::npos)
          throw "Incomplete variant for instruction '" + CGI.Name + "'!";
        LastEmitted = NP+1;
        if (AsmString[NP] == '}') {
          inVariant = false;        // No text for this variant.
          break;
        }
      }
    } else if (AsmString[DollarPos] == '|') {
      if (!inVariant)
        throw "'|' character found outside of a variant in instruction '"
          + CGI.Name + "'!";
      // Move to the end of variant list.
      std::string::size_type NP = AsmString.find('}', LastEmitted);
      if (NP == std::string::npos)
        throw "Incomplete variant for instruction '" + CGI.Name + "'!";
      LastEmitted = NP+1;
      inVariant = false;
    } else if (AsmString[DollarPos] == '}') {
      if (!inVariant)
        throw "'}' character found outside of a variant in instruction '"
          + CGI.Name + "'!";
      LastEmitted = DollarPos+1;
      inVariant = false;
    } else if (DollarPos+1 != AsmString.size() &&
               AsmString[DollarPos+1] == '$') {
      AddLiteralString("$");  // "$$" -> $
      LastEmitted = DollarPos+2;
    } else {
      // Get the name of the variable.
      // TODO: should eventually handle ${foo}bar as $foo
      std::string::size_type VarEnd = DollarPos+1;
      while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
        ++VarEnd;
      std::string VarName(AsmString.begin()+DollarPos+1,
                          AsmString.begin()+VarEnd);
      if (VarName.empty())
        throw "Stray '$' in '" + CGI.Name + "' asm string, maybe you want $$?";

      unsigned OpNo = CGI.getOperandNamed(VarName);
      CodeGenInstruction::OperandInfo OpInfo = CGI.OperandList[OpNo];

      // If this is a two-address instruction and we are not accessing the
      // 0th operand, remove an operand.
      unsigned MIOp = OpInfo.MIOperandNo;
      if (CGI.isTwoAddress && MIOp != 0) {
        if (MIOp == 1)
          throw "Should refer to operand #0 instead of #1 for two-address"
            " instruction '" + CGI.Name + "'!";
        --MIOp;
      }

      Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName,
                                          MIOp, OpInfo.Ty));
      LastEmitted = VarEnd;
    }
  }

  AddLiteralString("\\n");
}

/// MatchesAllButOneOp - If this instruction is exactly identical to the
/// specified instruction except for one differing operand, return the differing
/// operand number.  If more than one operand mismatches, return ~1, otherwise
/// if the instructions are identical return ~0.
unsigned AsmWriterInst::MatchesAllButOneOp(const AsmWriterInst &Other)const{
  if (Operands.size() != Other.Operands.size()) return ~1;

  unsigned MismatchOperand = ~0U;
  for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
    if (Operands[i] != Other.Operands[i])
      if (MismatchOperand != ~0U)  // Already have one mismatch?
        return ~1U;
      else
        MismatchOperand = i;
  }
  return MismatchOperand;
}

static void PrintCases(std::vector<std::pair<std::string,
                       AsmWriterOperand> > &OpsToPrint, std::ostream &O) {
  O << "    case " << OpsToPrint.back().first << ": ";
  AsmWriterOperand TheOp = OpsToPrint.back().second;
  OpsToPrint.pop_back();

  // Check to see if any other operands are identical in this list, and if so,
  // emit a case label for them.
  for (unsigned i = OpsToPrint.size(); i != 0; --i)
    if (OpsToPrint[i-1].second == TheOp) {
      O << "\n    case " << OpsToPrint[i-1].first << ": ";
      OpsToPrint.erase(OpsToPrint.begin()+i-1);
    }

  // Finally, emit the code.
  TheOp.EmitCode(O);
  O << "break;\n";
}

/// EmitInstructions - Emit the last instruction in the vector and any other
/// instructions that are suitably similar to it.
static void EmitInstructions(std::vector<AsmWriterInst> &Insts,
                             std::ostream &O) {
  AsmWriterInst FirstInst = Insts.back();
  Insts.pop_back();

  std::vector<AsmWriterInst> SimilarInsts;
  unsigned DifferingOperand = ~0;
  for (unsigned i = Insts.size(); i != 0; --i) {
    unsigned DiffOp = Insts[i-1].MatchesAllButOneOp(FirstInst);
    if (DiffOp != ~1U) {
      if (DifferingOperand == ~0U)  // First match!
        DifferingOperand = DiffOp;

      // If this differs in the same operand as the rest of the instructions in
      // this class, move it to the SimilarInsts list.
      if (DifferingOperand == DiffOp || DiffOp == ~0U) {
        SimilarInsts.push_back(Insts[i-1]);
        Insts.erase(Insts.begin()+i-1);
      }
    }
  }

  std::string Namespace = FirstInst.CGI->Namespace;

  O << "  case " << Namespace << "::"
    << FirstInst.CGI->TheDef->getName() << ":\n";
  for (unsigned i = 0, e = SimilarInsts.size(); i != e; ++i)
    O << "  case " << Namespace << "::"
      << SimilarInsts[i].CGI->TheDef->getName() << ":\n";
  for (unsigned i = 0, e = FirstInst.Operands.size(); i != e; ++i) {
    if (i != DifferingOperand) {
      // If the operand is the same for all instructions, just print it.
      O << "    ";
      FirstInst.Operands[i].EmitCode(O);
    } else {
      // If this is the operand that varies between all of the instructions,
      // emit a switch for just this operand now.
      O << "    switch (MI->getOpcode()) {\n";
      std::vector<std::pair<std::string, AsmWriterOperand> > OpsToPrint;
      OpsToPrint.push_back(std::make_pair(Namespace+"::"+
                                          FirstInst.CGI->TheDef->getName(),
                                          FirstInst.Operands[i]));

      for (unsigned si = 0, e = SimilarInsts.size(); si != e; ++si) {
        AsmWriterInst &AWI = SimilarInsts[si];
        OpsToPrint.push_back(std::make_pair(Namespace+"::"+
                                            AWI.CGI->TheDef->getName(),
                                            AWI.Operands[i]));
      }
      std::reverse(OpsToPrint.begin(), OpsToPrint.end());
      while (!OpsToPrint.empty())
        PrintCases(OpsToPrint, O);
      O << "    }";
    }
    O << "\n";
  }

  O << "    break;\n";
}

void AsmWriterEmitter::run(std::ostream &O) {
  EmitSourceFileHeader("Assembly Writer Source Fragment", O);

  CodeGenTarget Target;
  Record *AsmWriter = Target.getAsmWriter();
  std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
  unsigned Variant = AsmWriter->getValueAsInt("Variant");

  O <<
  "/// printInstruction - This method is automatically generated by tablegen\n"
  "/// from the instruction set description.  This method returns true if the\n"
  "/// machine instruction was sufficiently described to print it, otherwise\n"
  "/// it returns false.\n"
    "bool " << Target.getName() << ClassName
            << "::printInstruction(const MachineInstr *MI) {\n";

  std::string Namespace = Target.inst_begin()->second.Namespace;

  std::vector<AsmWriterInst> Instructions;

  for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
         E = Target.inst_end(); I != E; ++I)
    if (!I->second.AsmString.empty())
      Instructions.push_back(AsmWriterInst(I->second, Variant));

  // If all of the instructions start with a constant string (a very very common
  // occurance), emit all of the constant strings as a big table lookup instead
  // of requiring a switch for them.
  bool AllStartWithString = true;

  for (unsigned i = 0, e = Instructions.size(); i != e; ++i)
    if (Instructions[i].Operands.empty() ||
        Instructions[i].Operands[0].OperandType !=
                          AsmWriterOperand::isLiteralTextOperand) {
      AllStartWithString = false;
      break;
    }

  if (AllStartWithString) {
    // Compute the CodeGenInstruction -> AsmWriterInst mapping.  Note that not
    // all machine instructions are necessarily being printed, so there may be
    // target instructions not in this map.
    std::map<const CodeGenInstruction*, AsmWriterInst*> CGIAWIMap;
    for (unsigned i = 0, e = Instructions.size(); i != e; ++i)
      CGIAWIMap.insert(std::make_pair(Instructions[i].CGI, &Instructions[i]));

    // Emit a table of constant strings.
    std::vector<const CodeGenInstruction*> NumberedInstructions;
    Target.getInstructionsByEnumValue(NumberedInstructions);

    O << "  static const char * const OpStrs[] = {\n";
    for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
      AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions[i]];
      if (AWI == 0) {
        // Something not handled by the asmwriter printer.
        O << "    0,\t// ";
      } else {
        O << "    \"" << AWI->Operands[0].Str << "\",\t// ";
        // Nuke the string from the operand list.  It is now handled!
        AWI->Operands.erase(AWI->Operands.begin());
      }
      O << NumberedInstructions[i]->TheDef->getName() << "\n";
    }
    O << "  };\n\n"
      << "  // Emit the opcode for the instruction.\n"
      << "  if (const char *AsmStr = OpStrs[MI->getOpcode()])\n"
      << "    O << AsmStr;\n\n";
  }

  // Because this is a vector we want to emit from the end.  Reverse all of the
  // elements in the vector.
  std::reverse(Instructions.begin(), Instructions.end());

  O << "  switch (MI->getOpcode()) {\n"
       "  default: return false;\n";

  while (!Instructions.empty())
    EmitInstructions(Instructions, O);

  O << "  }\n"
       "  return true;\n"
       "}\n";
}
<commit_msg>Minor fix.<commit_after>//===- AsmWriterEmitter.cpp - Generate an assembly writer -----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend is emits an assembly printer for the current target.
// Note that this is currently fairly skeletal, but will grow over time.
//
//===----------------------------------------------------------------------===//

#include "AsmWriterEmitter.h"
#include "CodeGenTarget.h"
#include "Record.h"
#include <algorithm>
#include <ostream>
using namespace llvm;

static bool isIdentChar(char C) {
  return (C >= 'a' && C <= 'z') ||
         (C >= 'A' && C <= 'Z') ||
         (C >= '0' && C <= '9') ||
         C == '_';
}

namespace {
  struct AsmWriterOperand {
    enum { isLiteralTextOperand, isMachineInstrOperand } OperandType;

    /// Str - For isLiteralTextOperand, this IS the literal text.  For
    /// isMachineInstrOperand, this is the PrinterMethodName for the operand.
    std::string Str;

    /// MiOpNo - For isMachineInstrOperand, this is the operand number of the
    /// machine instruction.
    unsigned MIOpNo;

    /// OpVT - For isMachineInstrOperand, this is the value type for the
    /// operand.
    MVT::ValueType OpVT;

    AsmWriterOperand(const std::string &LitStr)
      : OperandType(isLiteralTextOperand),  Str(LitStr) {}

    AsmWriterOperand(const std::string &Printer, unsigned OpNo,
                     MVT::ValueType VT) : OperandType(isMachineInstrOperand),
                                          Str(Printer), MIOpNo(OpNo), OpVT(VT){}

    bool operator!=(const AsmWriterOperand &Other) const {
      if (OperandType != Other.OperandType || Str != Other.Str) return true;
      if (OperandType == isMachineInstrOperand)
        return MIOpNo != Other.MIOpNo || OpVT != Other.OpVT;
      return false;
    }
    bool operator==(const AsmWriterOperand &Other) const {
      return !operator!=(Other);
    }
    void EmitCode(std::ostream &OS) const;
  };

  struct AsmWriterInst {
    std::vector<AsmWriterOperand> Operands;
    const CodeGenInstruction *CGI;

    AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant);

    /// MatchesAllButOneOp - If this instruction is exactly identical to the
    /// specified instruction except for one differing operand, return the
    /// differing operand number.  Otherwise return ~0.
    unsigned MatchesAllButOneOp(const AsmWriterInst &Other) const;

  private:
    void AddLiteralString(const std::string &Str) {
      // If the last operand was already a literal text string, append this to
      // it, otherwise add a new operand.
      if (!Operands.empty() &&
          Operands.back().OperandType == AsmWriterOperand::isLiteralTextOperand)
        Operands.back().Str.append(Str);
      else
        Operands.push_back(AsmWriterOperand(Str));
    }
  };
}

void AsmWriterOperand::EmitCode(std::ostream &OS) const {
  if (OperandType == isLiteralTextOperand)
    OS << "O << \"" << Str << "\"; ";
  else
    OS << Str << "(MI, " << MIOpNo << ", MVT::" << getEnumName(OpVT) << "); ";
}

/// ParseAsmString - Parse the specified Instruction's AsmString into this
/// AsmWriterInst.
///
AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) {
  this->CGI = &CGI;
  bool inVariant = false;  // True if we are inside a {.|.|.} region.

  const std::string &AsmString = CGI.AsmString;
  std::string::size_type LastEmitted = 0;
  while (LastEmitted != AsmString.size()) {
    std::string::size_type DollarPos =
      AsmString.find_first_of("${|}", LastEmitted);
    if (DollarPos == std::string::npos) DollarPos = AsmString.size();

    // Emit a constant string fragment.
    if (DollarPos != LastEmitted) {
      // TODO: this should eventually handle escaping.
      AddLiteralString(std::string(AsmString.begin()+LastEmitted,
                                   AsmString.begin()+DollarPos));
      LastEmitted = DollarPos;
    } else if (AsmString[DollarPos] == '{') {
      if (inVariant)
        throw "Nested variants found for instruction '" + CGI.Name + "'!";
      LastEmitted = DollarPos+1;
      inVariant = true;   // We are now inside of the variant!
      for (unsigned i = 0; i != Variant; ++i) {
        // Skip over all of the text for an irrelevant variant here.  The
        // next variant starts at |, or there may not be text for this
        // variant if we see a }.
        std::string::size_type NP =
          AsmString.find_first_of("|}", LastEmitted);
        if (NP == std::string::npos)
          throw "Incomplete variant for instruction '" + CGI.Name + "'!";
        LastEmitted = NP+1;
        if (AsmString[NP] == '}') {
          inVariant = false;        // No text for this variant.
          break;
        }
      }
    } else if (AsmString[DollarPos] == '|') {
      if (!inVariant)
        throw "'|' character found outside of a variant in instruction '"
          + CGI.Name + "'!";
      // Move to the end of variant list.
      std::string::size_type NP = AsmString.find('}', LastEmitted);
      if (NP == std::string::npos)
        throw "Incomplete variant for instruction '" + CGI.Name + "'!";
      LastEmitted = NP+1;
      inVariant = false;
    } else if (AsmString[DollarPos] == '}') {
      if (!inVariant)
        throw "'}' character found outside of a variant in instruction '"
          + CGI.Name + "'!";
      LastEmitted = DollarPos+1;
      inVariant = false;
    } else if (DollarPos+1 != AsmString.size() &&
               AsmString[DollarPos+1] == '$') {
      AddLiteralString("$");  // "$$" -> $
      LastEmitted = DollarPos+2;
    } else {
      // Get the name of the variable.
      // TODO: should eventually handle ${foo}bar as $foo
      std::string::size_type VarEnd = DollarPos+1;
      while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
        ++VarEnd;
      std::string VarName(AsmString.begin()+DollarPos+1,
                          AsmString.begin()+VarEnd);
      if (VarName.empty())
        throw "Stray '$' in '" + CGI.Name + "' asm string, maybe you want $$?";

      unsigned OpNo = CGI.getOperandNamed(VarName);
      CodeGenInstruction::OperandInfo OpInfo = CGI.OperandList[OpNo];

      // If this is a two-address instruction and we are not accessing the
      // 0th operand, remove an operand.
      unsigned MIOp = OpInfo.MIOperandNo;
      if (CGI.isTwoAddress && MIOp != 0) {
        if (MIOp == 1)
          throw "Should refer to operand #0 instead of #1 for two-address"
            " instruction '" + CGI.Name + "'!";
        --MIOp;
      }

      Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName,
                                          MIOp, OpInfo.Ty));
      LastEmitted = VarEnd;
    }
  }

  AddLiteralString("\\n");
}

/// MatchesAllButOneOp - If this instruction is exactly identical to the
/// specified instruction except for one differing operand, return the differing
/// operand number.  If more than one operand mismatches, return ~1, otherwise
/// if the instructions are identical return ~0.
unsigned AsmWriterInst::MatchesAllButOneOp(const AsmWriterInst &Other)const{
  if (Operands.size() != Other.Operands.size()) return ~1;

  unsigned MismatchOperand = ~0U;
  for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
    if (Operands[i] != Other.Operands[i])
      if (MismatchOperand != ~0U)  // Already have one mismatch?
        return ~1U;
      else
        MismatchOperand = i;
  }
  return MismatchOperand;
}

static void PrintCases(std::vector<std::pair<std::string,
                       AsmWriterOperand> > &OpsToPrint, std::ostream &O) {
  O << "    case " << OpsToPrint.back().first << ": ";
  AsmWriterOperand TheOp = OpsToPrint.back().second;
  OpsToPrint.pop_back();

  // Check to see if any other operands are identical in this list, and if so,
  // emit a case label for them.
  for (unsigned i = OpsToPrint.size(); i != 0; --i)
    if (OpsToPrint[i-1].second == TheOp) {
      O << "\n    case " << OpsToPrint[i-1].first << ": ";
      OpsToPrint.erase(OpsToPrint.begin()+i-1);
    }

  // Finally, emit the code.
  TheOp.EmitCode(O);
  O << "break;\n";
}

/// EmitInstructions - Emit the last instruction in the vector and any other
/// instructions that are suitably similar to it.
static void EmitInstructions(std::vector<AsmWriterInst> &Insts,
                             std::ostream &O) {
  AsmWriterInst FirstInst = Insts.back();
  Insts.pop_back();

  std::vector<AsmWriterInst> SimilarInsts;
  unsigned DifferingOperand = ~0;
  for (unsigned i = Insts.size(); i != 0; --i) {
    unsigned DiffOp = Insts[i-1].MatchesAllButOneOp(FirstInst);
    if (DiffOp != ~1U) {
      if (DifferingOperand == ~0U)  // First match!
        DifferingOperand = DiffOp;

      // If this differs in the same operand as the rest of the instructions in
      // this class, move it to the SimilarInsts list.
      if (DifferingOperand == DiffOp || DiffOp == ~0U) {
        SimilarInsts.push_back(Insts[i-1]);
        Insts.erase(Insts.begin()+i-1);
      }
    }
  }

  std::string Namespace = FirstInst.CGI->Namespace;

  O << "  case " << Namespace << "::"
    << FirstInst.CGI->TheDef->getName() << ":\n";
  for (unsigned i = 0, e = SimilarInsts.size(); i != e; ++i)
    O << "  case " << Namespace << "::"
      << SimilarInsts[i].CGI->TheDef->getName() << ":\n";
  for (unsigned i = 0, e = FirstInst.Operands.size(); i != e; ++i) {
    if (i != DifferingOperand) {
      // If the operand is the same for all instructions, just print it.
      O << "    ";
      FirstInst.Operands[i].EmitCode(O);
    } else {
      // If this is the operand that varies between all of the instructions,
      // emit a switch for just this operand now.
      O << "    switch (MI->getOpcode()) {\n";
      std::vector<std::pair<std::string, AsmWriterOperand> > OpsToPrint;
      OpsToPrint.push_back(std::make_pair(Namespace+"::"+
                                          FirstInst.CGI->TheDef->getName(),
                                          FirstInst.Operands[i]));

      for (unsigned si = 0, e = SimilarInsts.size(); si != e; ++si) {
        AsmWriterInst &AWI = SimilarInsts[si];
        OpsToPrint.push_back(std::make_pair(Namespace+"::"+
                                            AWI.CGI->TheDef->getName(),
                                            AWI.Operands[i]));
      }
      std::reverse(OpsToPrint.begin(), OpsToPrint.end());
      while (!OpsToPrint.empty())
        PrintCases(OpsToPrint, O);
      O << "    }";
    }
    O << "\n";
  }

  O << "    break;\n";
}

void AsmWriterEmitter::run(std::ostream &O) {
  EmitSourceFileHeader("Assembly Writer Source Fragment", O);

  CodeGenTarget Target;
  Record *AsmWriter = Target.getAsmWriter();
  std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
  unsigned Variant = AsmWriter->getValueAsInt("Variant");

  O <<
  "/// printInstruction - This method is automatically generated by tablegen\n"
  "/// from the instruction set description.  This method returns true if the\n"
  "/// machine instruction was sufficiently described to print it, otherwise\n"
  "/// it returns false.\n"
    "bool " << Target.getName() << ClassName
            << "::printInstruction(const MachineInstr *MI) {\n";

  std::string Namespace = Target.inst_begin()->second.Namespace;

  std::vector<AsmWriterInst> Instructions;

  for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
         E = Target.inst_end(); I != E; ++I)
    if (!I->second.AsmString.empty())
      Instructions.push_back(AsmWriterInst(I->second, Variant));

  // If all of the instructions start with a constant string (a very very common
  // occurance), emit all of the constant strings as a big table lookup instead
  // of requiring a switch for them.
  bool AllStartWithString = true;

  for (unsigned i = 0, e = Instructions.size(); i != e; ++i)
    if (Instructions[i].Operands.empty() ||
        Instructions[i].Operands[0].OperandType !=
                          AsmWriterOperand::isLiteralTextOperand) {
      AllStartWithString = false;
      break;
    }

  if (AllStartWithString) {
    // Compute the CodeGenInstruction -> AsmWriterInst mapping.  Note that not
    // all machine instructions are necessarily being printed, so there may be
    // target instructions not in this map.
    std::map<const CodeGenInstruction*, AsmWriterInst*> CGIAWIMap;
    for (unsigned i = 0, e = Instructions.size(); i != e; ++i)
      CGIAWIMap.insert(std::make_pair(Instructions[i].CGI, &Instructions[i]));

    // Emit a table of constant strings.
    std::vector<const CodeGenInstruction*> NumberedInstructions;
    Target.getInstructionsByEnumValue(NumberedInstructions);

    O << "  static const char * const OpStrs[] = {\n";
    for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
      AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions[i]];
      if (AWI == 0) {
        // Something not handled by the asmwriter printer.
        O << "    0,\t// ";
      } else {
        O << "    \"" << AWI->Operands[0].Str << "\",\t// ";
        // Nuke the string from the operand list.  It is now handled!
        AWI->Operands.erase(AWI->Operands.begin());
      }
      O << NumberedInstructions[i]->TheDef->getName() << "\n";
    }
    O << "  };\n\n"
      << "  // Emit the opcode for the instruction.\n"
      << "  if (const char *AsmStr = OpStrs[MI->getOpcode()])\n"
      << "    O << AsmStr;\n\n";
  }

  // Because this is a vector we want to emit from the end.  Reverse all of the
  // elements in the vector.
  std::reverse(Instructions.begin(), Instructions.end());

  O << "  switch (MI->getOpcode()) {\n"
       "  default: return false;\n";

  while (!Instructions.empty())
    EmitInstructions(Instructions, O);

  O << "  }\n"
       "  return true;\n"
       "}\n";
}
<|endoftext|>


<commit_before>//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. ------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend is responsible for emitting a description of the target
// instruction set for the code generator.
//
//===----------------------------------------------------------------------===//

#include "InstrInfoEmitter.h"
#include "CodeGenTarget.h"
#include "Record.h"
using namespace llvm;

// runEnums - Print out enum values for all of the instructions.
void InstrInfoEmitter::runEnums(std::ostream &OS) {
  EmitSourceFileHeader("Target Instruction Enum Values", OS);
  OS << "namespace llvm {\n\n";

  CodeGenTarget Target;

  // We must emit the PHI opcode first...
  Record *InstrInfo = Target.getInstructionSet();

  std::string Namespace = Target.inst_begin()->second.Namespace;

  if (!Namespace.empty())
    OS << "namespace " << Namespace << " {\n";
  OS << "  enum {\n";

  std::vector<const CodeGenInstruction*> NumberedInstructions;
  Target.getInstructionsByEnumValue(NumberedInstructions);

  for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
    OS << "    " << NumberedInstructions[i]->TheDef->getName()
       << ", \t// " << i << "\n";
  }
  OS << "  };\n";
  if (!Namespace.empty())
    OS << "}\n";
  OS << "} // End llvm namespace \n";
}

void InstrInfoEmitter::printDefList(ListInit *LI, const std::string &Name,
                                    std::ostream &OS) const {
  OS << "static const unsigned " << Name << "[] = { ";
  for (unsigned j = 0, e = LI->getSize(); j != e; ++j)
    if (DefInit *DI = dynamic_cast<DefInit*>(LI->getElement(j)))
      OS << getQualifiedName(DI->getDef()) << ", ";
    else
      throw "Illegal value in '" + Name + "' list!";
  OS << "0 };\n";
}

// run - Emit the main instruction description records for the target...
void InstrInfoEmitter::run(std::ostream &OS) {
  EmitSourceFileHeader("Target Instruction Descriptors", OS);
  OS << "namespace llvm {\n\n";

  CodeGenTarget Target;
  const std::string &TargetName = Target.getName();
  Record *InstrInfo = Target.getInstructionSet();
  Record *PHI = InstrInfo->getValueAsDef("PHIInst");

  // Emit empty implicit uses and defs lists
  OS << "static const unsigned EmptyImpUses[] = { 0 };\n"
     << "static const unsigned EmptyImpDefs[] = { 0 };\n";

  // Emit all of the instruction's implicit uses and defs...
  for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
         E = Target.inst_end(); II != E; ++II) {
    Record *Inst = II->second.TheDef;
    ListInit *LI = Inst->getValueAsListInit("Uses");
    if (LI->getSize()) printDefList(LI, Inst->getName()+"ImpUses", OS);
    LI = Inst->getValueAsListInit("Defs");
    if (LI->getSize()) printDefList(LI, Inst->getName()+"ImpDefs", OS);
  }

  OS << "\nstatic const TargetInstrDescriptor " << TargetName
     << "Insts[] = {\n";
  emitRecord(Target.getPHIInstruction(), 0, InstrInfo, OS);

  unsigned i = 0;
  for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
         E = Target.inst_end(); II != E; ++II)
    if (II->second.TheDef != PHI)
      emitRecord(II->second, ++i, InstrInfo, OS);
  OS << "};\n";
  OS << "} // End llvm namespace \n";
}

void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
                                  Record *InstrInfo, std::ostream &OS) {
  OS << "  { \"";
  if (Inst.Name.empty())
    OS << Inst.TheDef->getName();
  else
    OS << Inst.Name;
  OS << "\",\t-1, -1, 0, false, 0, 0, 0, 0";

  // Emit all of the target indepedent flags...
  if (Inst.isReturn)     OS << "|M_RET_FLAG";
  if (Inst.isBranch)     OS << "|M_BRANCH_FLAG";
  if (Inst.isBarrier)    OS << "|M_BARRIER_FLAG";
  if (Inst.hasDelaySlot) OS << "|M_DELAY_SLOT_FLAG";
  if (Inst.isCall)       OS << "|M_CALL_FLAG";
  if (Inst.isLoad)       OS << "|M_LOAD_FLAG";
  if (Inst.isStore)      OS << "|M_STORE_FLAG";
  if (Inst.isTwoAddress) OS << "|M_2_ADDR_FLAG";
  if (Inst.isConvertibleToThreeAddress) OS << "|M_CONVERTIBLE_TO_3_ADDR";
  if (Inst.isCommutable) OS << "|M_COMMUTABLE";
  if (Inst.isTerminator) OS << "|M_TERMINATOR_FLAG";
  OS << ", 0";

  // Emit all of the target-specific flags...
  ListInit *LI    = InstrInfo->getValueAsListInit("TSFlagsFields");
  ListInit *Shift = InstrInfo->getValueAsListInit("TSFlagsShifts");
  if (LI->getSize() != Shift->getSize())
    throw "Lengths of " + InstrInfo->getName() +
          ":(TargetInfoFields, TargetInfoPositions) must be equal!";

  for (unsigned i = 0, e = LI->getSize(); i != e; ++i)
    emitShiftedValue(Inst.TheDef, dynamic_cast<StringInit*>(LI->getElement(i)),
                     dynamic_cast<IntInit*>(Shift->getElement(i)), OS);

  OS << ", ";

  // Emit the implicit uses and defs lists...
  LI = Inst.TheDef->getValueAsListInit("Uses");
  if (!LI->getSize())
    OS << "EmptyImpUses, ";
  else
    OS << Inst.TheDef->getName() << "ImpUses, ";

  LI = Inst.TheDef->getValueAsListInit("Defs");
  if (!LI->getSize())
    OS << "EmptyImpDefs ";
  else
    OS << Inst.TheDef->getName() << "ImpDefs ";

  OS << " },  // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n";
}

void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val,
                                        IntInit *ShiftInt, std::ostream &OS) {
  if (Val == 0 || ShiftInt == 0)
    throw std::string("Illegal value or shift amount in TargetInfo*!");
  RecordVal *RV = R->getValue(Val->getValue());
  int Shift = ShiftInt->getValue();

  if (RV == 0 || RV->getValue() == 0)
    throw R->getName() + " doesn't have a field named '" + Val->getValue()+"'!";

  Init *Value = RV->getValue();
  if (BitInit *BI = dynamic_cast<BitInit*>(Value)) {
    if (BI->getValue()) OS << "|(1<<" << Shift << ")";
    return;
  } else if (BitsInit *BI = dynamic_cast<BitsInit*>(Value)) {
    // Convert the Bits to an integer to print...
    Init *I = BI->convertInitializerTo(new IntRecTy());
    if (I)
      if (IntInit *II = dynamic_cast<IntInit*>(I)) {
        if (II->getValue())
          OS << "|(" << II->getValue() << "<<" << Shift << ")";
        return;
      }

  } else if (IntInit *II = dynamic_cast<IntInit*>(Value)) {
    if (II->getValue()) OS << "|(" << II->getValue() << "<<" << Shift << ")";
    return;
  }

  std::cerr << "Unhandled initializer: " << *Val << "\n";
  throw "In record '" + R->getName() + "' for TSFlag emission.";
}

<commit_msg>Fill in the numOperands field of the TargetInstrDescriptor struct from the .td file.<commit_after>//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. ------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend is responsible for emitting a description of the target
// instruction set for the code generator.
//
//===----------------------------------------------------------------------===//

#include "InstrInfoEmitter.h"
#include "CodeGenTarget.h"
#include "Record.h"
using namespace llvm;

// runEnums - Print out enum values for all of the instructions.
void InstrInfoEmitter::runEnums(std::ostream &OS) {
  EmitSourceFileHeader("Target Instruction Enum Values", OS);
  OS << "namespace llvm {\n\n";

  CodeGenTarget Target;

  // We must emit the PHI opcode first...
  Record *InstrInfo = Target.getInstructionSet();

  std::string Namespace = Target.inst_begin()->second.Namespace;

  if (!Namespace.empty())
    OS << "namespace " << Namespace << " {\n";
  OS << "  enum {\n";

  std::vector<const CodeGenInstruction*> NumberedInstructions;
  Target.getInstructionsByEnumValue(NumberedInstructions);

  for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
    OS << "    " << NumberedInstructions[i]->TheDef->getName()
       << ", \t// " << i << "\n";
  }
  OS << "  };\n";
  if (!Namespace.empty())
    OS << "}\n";
  OS << "} // End llvm namespace \n";
}

void InstrInfoEmitter::printDefList(ListInit *LI, const std::string &Name,
                                    std::ostream &OS) const {
  OS << "static const unsigned " << Name << "[] = { ";
  for (unsigned j = 0, e = LI->getSize(); j != e; ++j)
    if (DefInit *DI = dynamic_cast<DefInit*>(LI->getElement(j)))
      OS << getQualifiedName(DI->getDef()) << ", ";
    else
      throw "Illegal value in '" + Name + "' list!";
  OS << "0 };\n";
}

// run - Emit the main instruction description records for the target...
void InstrInfoEmitter::run(std::ostream &OS) {
  EmitSourceFileHeader("Target Instruction Descriptors", OS);
  OS << "namespace llvm {\n\n";

  CodeGenTarget Target;
  const std::string &TargetName = Target.getName();
  Record *InstrInfo = Target.getInstructionSet();
  Record *PHI = InstrInfo->getValueAsDef("PHIInst");

  // Emit empty implicit uses and defs lists
  OS << "static const unsigned EmptyImpUses[] = { 0 };\n"
     << "static const unsigned EmptyImpDefs[] = { 0 };\n";

  // Emit all of the instruction's implicit uses and defs...
  for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
         E = Target.inst_end(); II != E; ++II) {
    Record *Inst = II->second.TheDef;
    ListInit *LI = Inst->getValueAsListInit("Uses");
    if (LI->getSize()) printDefList(LI, Inst->getName()+"ImpUses", OS);
    LI = Inst->getValueAsListInit("Defs");
    if (LI->getSize()) printDefList(LI, Inst->getName()+"ImpDefs", OS);
  }

  OS << "\nstatic const TargetInstrDescriptor " << TargetName
     << "Insts[] = {\n";
  emitRecord(Target.getPHIInstruction(), 0, InstrInfo, OS);

  unsigned i = 0;
  for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
         E = Target.inst_end(); II != E; ++II)
    if (II->second.TheDef != PHI)
      emitRecord(II->second, ++i, InstrInfo, OS);
  OS << "};\n";
  OS << "} // End llvm namespace \n";
}

void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
                                  Record *InstrInfo, std::ostream &OS) {
  OS << "  { \"";
  if (Inst.Name.empty())
    OS << Inst.TheDef->getName();
  else
    OS << Inst.Name;
  OS << "\",\t" << Inst.OperandList.size() << ", -1, 0, false, 0, 0, 0, 0";

  // Emit all of the target indepedent flags...
  if (Inst.isReturn)     OS << "|M_RET_FLAG";
  if (Inst.isBranch)     OS << "|M_BRANCH_FLAG";
  if (Inst.isBarrier)    OS << "|M_BARRIER_FLAG";
  if (Inst.hasDelaySlot) OS << "|M_DELAY_SLOT_FLAG";
  if (Inst.isCall)       OS << "|M_CALL_FLAG";
  if (Inst.isLoad)       OS << "|M_LOAD_FLAG";
  if (Inst.isStore)      OS << "|M_STORE_FLAG";
  if (Inst.isTwoAddress) OS << "|M_2_ADDR_FLAG";
  if (Inst.isConvertibleToThreeAddress) OS << "|M_CONVERTIBLE_TO_3_ADDR";
  if (Inst.isCommutable) OS << "|M_COMMUTABLE";
  if (Inst.isTerminator) OS << "|M_TERMINATOR_FLAG";
  OS << ", 0";

  // Emit all of the target-specific flags...
  ListInit *LI    = InstrInfo->getValueAsListInit("TSFlagsFields");
  ListInit *Shift = InstrInfo->getValueAsListInit("TSFlagsShifts");
  if (LI->getSize() != Shift->getSize())
    throw "Lengths of " + InstrInfo->getName() +
          ":(TargetInfoFields, TargetInfoPositions) must be equal!";

  for (unsigned i = 0, e = LI->getSize(); i != e; ++i)
    emitShiftedValue(Inst.TheDef, dynamic_cast<StringInit*>(LI->getElement(i)),
                     dynamic_cast<IntInit*>(Shift->getElement(i)), OS);

  OS << ", ";

  // Emit the implicit uses and defs lists...
  LI = Inst.TheDef->getValueAsListInit("Uses");
  if (!LI->getSize())
    OS << "EmptyImpUses, ";
  else
    OS << Inst.TheDef->getName() << "ImpUses, ";

  LI = Inst.TheDef->getValueAsListInit("Defs");
  if (!LI->getSize())
    OS << "EmptyImpDefs ";
  else
    OS << Inst.TheDef->getName() << "ImpDefs ";

  OS << " },  // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n";
}

void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val,
                                        IntInit *ShiftInt, std::ostream &OS) {
  if (Val == 0 || ShiftInt == 0)
    throw std::string("Illegal value or shift amount in TargetInfo*!");
  RecordVal *RV = R->getValue(Val->getValue());
  int Shift = ShiftInt->getValue();

  if (RV == 0 || RV->getValue() == 0)
    throw R->getName() + " doesn't have a field named '" + Val->getValue()+"'!";

  Init *Value = RV->getValue();
  if (BitInit *BI = dynamic_cast<BitInit*>(Value)) {
    if (BI->getValue()) OS << "|(1<<" << Shift << ")";
    return;
  } else if (BitsInit *BI = dynamic_cast<BitsInit*>(Value)) {
    // Convert the Bits to an integer to print...
    Init *I = BI->convertInitializerTo(new IntRecTy());
    if (I)
      if (IntInit *II = dynamic_cast<IntInit*>(I)) {
        if (II->getValue())
          OS << "|(" << II->getValue() << "<<" << Shift << ")";
        return;
      }

  } else if (IntInit *II = dynamic_cast<IntInit*>(Value)) {
    if (II->getValue()) OS << "|(" << II->getValue() << "<<" << Shift << ")";
    return;
  }

  std::cerr << "Unhandled initializer: " << *Val << "\n";
  throw "In record '" + R->getName() + "' for TSFlag emission.";
}

<|endoftext|>


<commit_before>#include <osg/Texture2D>
#include <osg/TexGen>
#include <osg/Material>
#include <osg/LightSource>
#include <osg/Geode>
#include <osg/ShapeDrawable>

#include <osgUtil/CullVisitor>
#include <osgUtil/RenderToTextureStage>

#include "CreateShadowedScene.h"

using namespace osg;

class CreateShadowTextureCullCallback : public osg::NodeCallback
{
    public:

        CreateShadowTextureCullCallback(osg::Node* shadower,const osg::Vec3& position, const osg::Vec4& ambientLightColor, unsigned int textureUnit):
            _shadower(shadower),
            _position(position),
            _ambientLightColor(ambientLightColor),
            _unit(textureUnit),
            _shadowState(new osg::StateSet),
            _shadowedState(new osg::StateSet)
        {
            _texture = new osg::Texture2D;
            _texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
            _texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
            _texture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER);
            _texture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER);
            _texture->setBorderColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
        }

        virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
        {

            osgUtil::CullVisitor* cullVisitor = dynamic_cast<osgUtil::CullVisitor*>(nv);
            if (cullVisitor && (_texture.valid() && _shadower.valid()))
            {
                doPreRender(*node,*cullVisitor);

            }
            else
            {
                // must traverse the shadower
                traverse(node,nv);
            }
        }

    protected:

        void doPreRender(osg::Node& node, osgUtil::CullVisitor& cv);

        osg::ref_ptr<osg::Node>      _shadower;
        osg::ref_ptr<osg::Texture2D> _texture;
        osg::Vec3                    _position;
        osg::Vec4                    _ambientLightColor;
        unsigned int                 _unit;
        osg::ref_ptr<osg::StateSet>  _shadowState;
        osg::ref_ptr<osg::StateSet>  _shadowedState;

};

void CreateShadowTextureCullCallback::doPreRender(osg::Node& node, osgUtil::CullVisitor& cv)
{

    const osg::BoundingSphere& bs = _shadower->getBound();
    if (!bs.valid())
    {
        osg::notify(osg::WARN) << "bb invalid"<<_shadower.get()<<std::endl;
        return;
    }

    // create the render to texture stage.
    osg::ref_ptr<osgUtil::RenderToTextureStage> rtts = new osgUtil::RenderToTextureStage;

    // set up lighting.
    // currently ignore lights in the scene graph itself..
    // will do later.
    osgUtil::RenderStage* previous_stage = cv.getCurrentRenderBin()->getStage();

    // set up the background color and clear mask.
    rtts->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
    //rtts->setClearMask(previous_stage->getClearMask());

    // set up to charge the same RenderStageLighting is the parent previous stage.
    rtts->setRenderStageLighting(previous_stage->getRenderStageLighting());

    // record the render bin, to be restored after creation
    // of the render to text
    osgUtil::RenderBin* previousRenderBin = cv.getCurrentRenderBin();

    // set the current renderbin to be the newly created stage.
    cv.setCurrentRenderBin(rtts.get());

    float centerDistance = (_position-bs.center()).length();

    float znear = centerDistance-bs.radius();
    float zfar  = centerDistance+bs.radius();
    float zNearRatio = 0.001f;
    if (znear<zfar*zNearRatio) znear = zfar*zNearRatio;

    // 2:1 aspect ratio as per flag geomtry below.
    float top   = (bs.radius()/centerDistance)*znear;
    float right = top;

    // set up projection.
    osg::RefMatrix* projection = new osg::RefMatrix;
    projection->makeFrustum(-right,right,-top,top,znear,zfar);

    cv.pushProjectionMatrix(projection);

    osg::RefMatrix* matrix = new osg::RefMatrix;
    matrix->makeLookAt(_position,bs.center(),osg::Vec3(0.0f,1.0f,0.0f));

    osg::Matrix MV = cv.getModelViewMatrix();

    // compute the matrix which takes a vertex from local coords into tex coords
    // will use this later to specify osg::TexGen..
    osg::Matrix MVPT =
                       *matrix *
                       *projection *
                       osg::Matrix::translate(1.0,1.0,1.0) *
                       osg::Matrix::scale(0.5f,0.5f,0.5f);

    cv.pushModelViewMatrix(matrix);

    // make the material black for a shadow.
    osg::Material* material = new osg::Material;
    material->setAmbient(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,0.0f,0.0f,1.0f));
    material->setDiffuse(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,0.0f,0.0f,1.0f));
    material->setEmission(osg::Material::FRONT_AND_BACK,_ambientLightColor);
    material->setShininess(osg::Material::FRONT_AND_BACK,0.0f);
    _shadowState->setAttribute(material,osg::StateAttribute::OVERRIDE);

    cv.pushStateSet(_shadowState.get());

    {

        // traverse the shadower
        _shadower->accept(cv);

    }

    cv.popStateSet();

    // restore the previous model view matrix.
    cv.popModelViewMatrix();

    // restore the previous model view matrix.
    cv.popProjectionMatrix();

    // restore the previous renderbin.
    cv.setCurrentRenderBin(previousRenderBin);

    if (rtts->getRenderGraphList().size()==0 && rtts->getRenderBinList().size()==0)
    {
        // getting to this point means that all the shadower has been
        // culled by small feature culling or is beyond LOD ranges.
        return;
    }

    int height = 256;
    int width  = 256;

    const osg::Viewport& viewport = *cv.getViewport();

    // offset the impostor viewport from the center of the main window
    // viewport as often the edges of the viewport might be obscured by
    // other windows, which can cause image/reading writing problems.
    int center_x = viewport.x()+viewport.width()/2;
    int center_y = viewport.y()+viewport.height()/2;

    osg::Viewport* new_viewport = new osg::Viewport;
    new_viewport->setViewport(center_x-width/2,center_y-height/2,width,height);
    rtts->setViewport(new_viewport);

    _shadowState->setAttribute(new_viewport);

    // and the render to texture stage to the current stages
    // dependancy list.
    cv.getCurrentRenderBin()->getStage()->addToDependencyList(rtts.get());

    // if one exist attach texture to the RenderToTextureStage.
    if (_texture.valid()) rtts->setTexture(_texture.get());

    // set up the stateset to decorate the shadower with the shadow texture
    // with the appropriate tex gen coords.
    TexGen* texgen = new TexGen;
    //texgen->setMatrix(MV);
    texgen->setMode(osg::TexGen::EYE_LINEAR);
    texgen->setPlane(osg::TexGen::S,osg::Plane(MVPT(0,0),MVPT(1,0),MVPT(2,0),MVPT(3,0)));
    texgen->setPlane(osg::TexGen::T,osg::Plane(MVPT(0,1),MVPT(1,1),MVPT(2,1),MVPT(3,1)));
    texgen->setPlane(osg::TexGen::R,osg::Plane(MVPT(0,2),MVPT(1,2),MVPT(2,2),MVPT(3,2)));
    texgen->setPlane(osg::TexGen::Q,osg::Plane(MVPT(0,3),MVPT(1,3),MVPT(2,3),MVPT(3,3)));

    cv.getRenderStage()->addPositionedTextureAttribute(0,new osg::RefMatrix(MV),texgen);

    _shadowedState->setTextureAttributeAndModes(_unit,_texture.get(),osg::StateAttribute::ON);
    _shadowedState->setTextureAttribute(_unit,texgen);
    _shadowedState->setTextureMode(_unit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON);
    _shadowedState->setTextureMode(_unit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON);
    _shadowedState->setTextureMode(_unit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON);
    _shadowedState->setTextureMode(_unit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON);

    cv.pushStateSet(_shadowedState.get());

        // must traverse the shadower
        traverse(&node,&cv);

    cv.popStateSet();

}

// set up a light source with the shadower and shodower subgraphs below it
// with the appropriate callbacks set up.
osg::Group* createShadowedScene(osg::Node* shadower,osg::Node* shadowed,const osg::Vec3& lightPosition,float radius,unsigned int textureUnit)
{
    osg::LightSource* lightgroup = new osg::LightSource;

    osg::Light* light = new osg::Light;
    light->setPosition(osg::Vec4(lightPosition,1.0f));
    light->setLightNum(0);

    lightgroup->setLight(light);

    osg::Vec4 ambientLightColor(0.2,0.2f,0.2f,1.0f);

    // add the shadower
    lightgroup->addChild(shadower);

    // add the shadowed with the callback to generate the shadow texture.
    shadowed->setCullCallback(new CreateShadowTextureCullCallback(shadower,lightPosition,ambientLightColor,textureUnit));
    lightgroup->addChild(shadowed);

    osg::Geode* lightgeode = new osg::Geode;
    lightgeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
    lightgeode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(lightPosition,radius)));

    lightgroup->addChild(lightgeode);

    return lightgroup;
}

<commit_msg>Updated to use new TexGen method<commit_after>#include <osg/Texture2D>
#include <osg/TexGen>
#include <osg/Material>
#include <osg/LightSource>
#include <osg/Geode>
#include <osg/ShapeDrawable>

#include <osgUtil/CullVisitor>
#include <osgUtil/RenderToTextureStage>

#include "CreateShadowedScene.h"

using namespace osg;

class CreateShadowTextureCullCallback : public osg::NodeCallback
{
    public:

        CreateShadowTextureCullCallback(osg::Node* shadower,const osg::Vec3& position, const osg::Vec4& ambientLightColor, unsigned int textureUnit):
            _shadower(shadower),
            _position(position),
            _ambientLightColor(ambientLightColor),
            _unit(textureUnit),
            _shadowState(new osg::StateSet),
            _shadowedState(new osg::StateSet)
        {
            _texture = new osg::Texture2D;
            _texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
            _texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
            _texture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER);
            _texture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER);
            _texture->setBorderColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
        }

        virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
        {

            osgUtil::CullVisitor* cullVisitor = dynamic_cast<osgUtil::CullVisitor*>(nv);
            if (cullVisitor && (_texture.valid() && _shadower.valid()))
            {
                doPreRender(*node,*cullVisitor);

            }
            else
            {
                // must traverse the shadower
                traverse(node,nv);
            }
        }

    protected:

        void doPreRender(osg::Node& node, osgUtil::CullVisitor& cv);

        osg::ref_ptr<osg::Node>      _shadower;
        osg::ref_ptr<osg::Texture2D> _texture;
        osg::Vec3                    _position;
        osg::Vec4                    _ambientLightColor;
        unsigned int                 _unit;
        osg::ref_ptr<osg::StateSet>  _shadowState;
        osg::ref_ptr<osg::StateSet>  _shadowedState;

};

void CreateShadowTextureCullCallback::doPreRender(osg::Node& node, osgUtil::CullVisitor& cv)
{

    const osg::BoundingSphere& bs = _shadower->getBound();
    if (!bs.valid())
    {
        osg::notify(osg::WARN) << "bb invalid"<<_shadower.get()<<std::endl;
        return;
    }

    // create the render to texture stage.
    osg::ref_ptr<osgUtil::RenderToTextureStage> rtts = new osgUtil::RenderToTextureStage;

    // set up lighting.
    // currently ignore lights in the scene graph itself..
    // will do later.
    osgUtil::RenderStage* previous_stage = cv.getCurrentRenderBin()->getStage();

    // set up the background color and clear mask.
    rtts->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
    //rtts->setClearMask(previous_stage->getClearMask());

    // set up to charge the same RenderStageLighting is the parent previous stage.
    rtts->setRenderStageLighting(previous_stage->getRenderStageLighting());

    // record the render bin, to be restored after creation
    // of the render to text
    osgUtil::RenderBin* previousRenderBin = cv.getCurrentRenderBin();

    // set the current renderbin to be the newly created stage.
    cv.setCurrentRenderBin(rtts.get());

    float centerDistance = (_position-bs.center()).length();

    float znear = centerDistance-bs.radius();
    float zfar  = centerDistance+bs.radius();
    float zNearRatio = 0.001f;
    if (znear<zfar*zNearRatio) znear = zfar*zNearRatio;

    // 2:1 aspect ratio as per flag geomtry below.
    float top   = (bs.radius()/centerDistance)*znear;
    float right = top;

    // set up projection.
    osg::RefMatrix* projection = new osg::RefMatrix;
    projection->makeFrustum(-right,right,-top,top,znear,zfar);

    cv.pushProjectionMatrix(projection);

    osg::RefMatrix* matrix = new osg::RefMatrix;
    matrix->makeLookAt(_position,bs.center(),osg::Vec3(0.0f,1.0f,0.0f));

    osg::Matrix MV = cv.getModelViewMatrix();

    // compute the matrix which takes a vertex from local coords into tex coords
    // will use this later to specify osg::TexGen..
    osg::Matrix MVPT =
                       *matrix *
                       *projection *
                       osg::Matrix::translate(1.0,1.0,1.0) *
                       osg::Matrix::scale(0.5f,0.5f,0.5f);

    cv.pushModelViewMatrix(matrix);

    // make the material black for a shadow.
    osg::Material* material = new osg::Material;
    material->setAmbient(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,0.0f,0.0f,1.0f));
    material->setDiffuse(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,0.0f,0.0f,1.0f));
    material->setEmission(osg::Material::FRONT_AND_BACK,_ambientLightColor);
    material->setShininess(osg::Material::FRONT_AND_BACK,0.0f);
    _shadowState->setAttribute(material,osg::StateAttribute::OVERRIDE);

    cv.pushStateSet(_shadowState.get());

    {

        // traverse the shadower
        _shadower->accept(cv);

    }

    cv.popStateSet();

    // restore the previous model view matrix.
    cv.popModelViewMatrix();

    // restore the previous model view matrix.
    cv.popProjectionMatrix();

    // restore the previous renderbin.
    cv.setCurrentRenderBin(previousRenderBin);

    if (rtts->getRenderGraphList().size()==0 && rtts->getRenderBinList().size()==0)
    {
        // getting to this point means that all the shadower has been
        // culled by small feature culling or is beyond LOD ranges.
        return;
    }

    int height = 256;
    int width  = 256;

    const osg::Viewport& viewport = *cv.getViewport();

    // offset the impostor viewport from the center of the main window
    // viewport as often the edges of the viewport might be obscured by
    // other windows, which can cause image/reading writing problems.
    int center_x = viewport.x()+viewport.width()/2;
    int center_y = viewport.y()+viewport.height()/2;

    osg::Viewport* new_viewport = new osg::Viewport;
    new_viewport->setViewport(center_x-width/2,center_y-height/2,width,height);
    rtts->setViewport(new_viewport);

    _shadowState->setAttribute(new_viewport);

    // and the render to texture stage to the current stages
    // dependancy list.
    cv.getCurrentRenderBin()->getStage()->addToDependencyList(rtts.get());

    // if one exist attach texture to the RenderToTextureStage.
    if (_texture.valid()) rtts->setTexture(_texture.get());

    // set up the stateset to decorate the shadower with the shadow texture
    // with the appropriate tex gen coords.
    TexGen* texgen = new TexGen;
    //texgen->setMatrix(MV);
    texgen->setMode(osg::TexGen::EYE_LINEAR);
    texgen->setPlanesFromMatrix(MVPT);

    cv.getRenderStage()->addPositionedTextureAttribute(0,new osg::RefMatrix(MV),texgen);

    _shadowedState->setTextureAttributeAndModes(_unit,_texture.get(),osg::StateAttribute::ON);
    _shadowedState->setTextureAttribute(_unit,texgen);
    _shadowedState->setTextureMode(_unit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON);
    _shadowedState->setTextureMode(_unit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON);
    _shadowedState->setTextureMode(_unit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON);
    _shadowedState->setTextureMode(_unit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON);

    cv.pushStateSet(_shadowedState.get());

        // must traverse the shadower
        traverse(&node,&cv);

    cv.popStateSet();

}

// set up a light source with the shadower and shodower subgraphs below it
// with the appropriate callbacks set up.
osg::Group* createShadowedScene(osg::Node* shadower,osg::Node* shadowed,const osg::Vec3& lightPosition,float radius,unsigned int textureUnit)
{
    osg::LightSource* lightgroup = new osg::LightSource;

    osg::Light* light = new osg::Light;
    light->setPosition(osg::Vec4(lightPosition,1.0f));
    light->setLightNum(0);

    lightgroup->setLight(light);

    osg::Vec4 ambientLightColor(0.2,0.2f,0.2f,1.0f);

    // add the shadower
    lightgroup->addChild(shadower);

    // add the shadowed with the callback to generate the shadow texture.
    shadowed->setCullCallback(new CreateShadowTextureCullCallback(shadower,lightPosition,ambientLightColor,textureUnit));
    lightgroup->addChild(shadowed);

    osg::Geode* lightgeode = new osg::Geode;
    lightgeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
    lightgeode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(lightPosition,radius)));

    lightgroup->addChild(lightgeode);

    return lightgroup;
}

<|endoftext|>


<commit_before>//===- OptParserEmitter.cpp - Table Driven Command Line Parsing -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/TableGen/Error.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <cstring>
#include <map>
#include <strings.h>

using namespace llvm;

// Ordering on Info. The logic should match with the consumer-side function in
// llvm/Option/OptTable.h.
static int StrCmpOptionName(const char *A, const char *B) {
  size_t I = strlen(A);
  size_t J = strlen(B);
  if (I == J) {
    if (int N = strcasecmp(A, B))
      return N;
    return strcmp(A, B);
  }
  if (I < J)
    return strncasecmp(A, B, I) < 0 ? -1 : 1;
  return strncasecmp(A, B, J) <= 0 ? -1 : 1;
}

static int CompareOptionRecords(const void *Av, const void *Bv) {
  const Record *A = *(const Record*const*) Av;
  const Record *B = *(const Record*const*) Bv;

  // Sentinel options precede all others and are only ordered by precedence.
  bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel");
  bool BSent = B->getValueAsDef("Kind")->getValueAsBit("Sentinel");
  if (ASent != BSent)
    return ASent ? -1 : 1;

  // Compare options by name, unless they are sentinels.
  if (!ASent)
    if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").c_str(),
                                   B->getValueAsString("Name").c_str()))
      return Cmp;

  if (!ASent) {
    std::vector<std::string> APrefixes = A->getValueAsListOfStrings("Prefixes");
    std::vector<std::string> BPrefixes = B->getValueAsListOfStrings("Prefixes");

    for (std::vector<std::string>::const_iterator APre = APrefixes.begin(),
                                                  AEPre = APrefixes.end(),
                                                  BPre = BPrefixes.begin(),
                                                  BEPre = BPrefixes.end();
                                                  APre != AEPre &&
                                                  BPre != BEPre;
                                                  ++APre, ++BPre) {
      if (int Cmp = StrCmpOptionName(APre->c_str(), BPre->c_str()))
        return Cmp;
    }
  }

  // Then by the kind precedence;
  int APrec = A->getValueAsDef("Kind")->getValueAsInt("Precedence");
  int BPrec = B->getValueAsDef("Kind")->getValueAsInt("Precedence");
  if (APrec == BPrec &&
      A->getValueAsListOfStrings("Prefixes") ==
      B->getValueAsListOfStrings("Prefixes")) {
    PrintError(A->getLoc(), Twine("Option is equivilent to"));
    PrintError(B->getLoc(), Twine("Other defined here"));
    PrintFatalError("Equivalent Options found.");
  }
  return APrec < BPrec ? -1 : 1;
}

static const std::string getOptionName(const Record &R) {
  // Use the record name unless EnumName is defined.
  if (isa<UnsetInit>(R.getValueInit("EnumName")))
    return R.getName();

  return R.getValueAsString("EnumName");
}

static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) {
  OS << '"';
  OS.write_escaped(Str);
  OS << '"';
  return OS;
}

/// OptParserEmitter - This tablegen backend takes an input .td file
/// describing a list of options and emits a data structure for parsing and
/// working with those options when given an input command line.
namespace llvm {
void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
  // Get the option groups and options.
  const std::vector<Record*> &Groups =
    Records.getAllDerivedDefinitions("OptionGroup");
  std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");

  emitSourceFileHeader("Option Parsing Definitions", OS);

  array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
  // Generate prefix groups.
  typedef SmallVector<SmallString<2>, 2> PrefixKeyT;
  typedef std::map<PrefixKeyT, std::string> PrefixesT;
  PrefixesT Prefixes;
  Prefixes.insert(std::make_pair(PrefixKeyT(), "prefix_0"));
  unsigned CurPrefix = 0;
  for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
    const Record &R = *Opts[i];
    std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes");
    PrefixKeyT prfkey(prf.begin(), prf.end());
    unsigned NewPrefix = CurPrefix + 1;
    if (Prefixes.insert(std::make_pair(prfkey, (Twine("prefix_") +
                                              Twine(NewPrefix)).str())).second)
      CurPrefix = NewPrefix;
  }

  // Dump prefixes.

  OS << "/////////\n";
  OS << "// Prefixes\n\n";
  OS << "#ifdef PREFIX\n";
  OS << "#define COMMA ,\n";
  for (PrefixesT::const_iterator I = Prefixes.begin(), E = Prefixes.end();
                                  I != E; ++I) {
    OS << "PREFIX(";

    // Prefix name.
    OS << I->second;

    // Prefix values.
    OS << ", {";
    for (PrefixKeyT::const_iterator PI = I->first.begin(),
                                    PE = I->first.end(); PI != PE; ++PI) {
      OS << "\"" << *PI << "\" COMMA ";
    }
    OS << "0})\n";
  }
  OS << "#undef COMMA\n";
  OS << "#endif\n\n";

  OS << "/////////\n";
  OS << "// Groups\n\n";
  OS << "#ifdef OPTION\n";
  for (unsigned i = 0, e = Groups.size(); i != e; ++i) {
    const Record &R = *Groups[i];

    // Start a single option entry.
    OS << "OPTION(";

    // The option prefix;
    OS << "0";

    // The option string.
    OS << ", \"" << R.getValueAsString("Name") << '"';

    // The option identifier name.
    OS  << ", "<< getOptionName(R);

    // The option kind.
    OS << ", Group";

    // The containing option group (if any).
    OS << ", ";
    if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
      OS << getOptionName(*DI->getDef());
    else
      OS << "INVALID";

    // The other option arguments (unused for groups).
    OS << ", INVALID, 0, 0, 0";

    // The option help text.
    if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
      OS << ",\n";
      OS << "       ";
      write_cstring(OS, R.getValueAsString("HelpText"));
    } else
      OS << ", 0";

    // The option meta-variable name (unused).
    OS << ", 0)\n";
  }
  OS << "\n";

  OS << "//////////\n";
  OS << "// Options\n\n";
  for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
    const Record &R = *Opts[i];

    // Start a single option entry.
    OS << "OPTION(";

    // The option prefix;
    std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes");
    OS << Prefixes[PrefixKeyT(prf.begin(), prf.end())] << ", ";

    // The option string.
    write_cstring(OS, R.getValueAsString("Name"));

    // The option identifier name.
    OS  << ", "<< getOptionName(R);

    // The option kind.
    OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");

    // The containing option group (if any).
    OS << ", ";
    if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
      OS << getOptionName(*DI->getDef());
    else
      OS << "INVALID";

    // The option alias (if any).
    OS << ", ";
    if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Alias")))
      OS << getOptionName(*DI->getDef());
    else
      OS << "INVALID";

    // The option alias arguments (if any).
    // Emitted as a \0 separated list in a string, e.g. ["foo", "bar"]
    // would become "foo\0bar\0". Note that the compiler adds an implicit
    // terminating \0 at the end.
    OS << ", ";
    std::vector<std::string> AliasArgs = R.getValueAsListOfStrings("AliasArgs");
    if (AliasArgs.size() == 0) {
      OS << "0";
    } else {
      OS << "\"";
      for (size_t i = 0, e = AliasArgs.size(); i != e; ++i)
        OS << AliasArgs[i] << "\\0";
      OS << "\"";
    }

    // The option flags.
    const ListInit *LI = R.getValueAsListInit("Flags");
    if (LI->empty()) {
      OS << ", 0";
    } else {
      OS << ", ";
      for (unsigned i = 0, e = LI->size(); i != e; ++i) {
        if (i)
          OS << " | ";
        OS << cast<DefInit>(LI->getElement(i))->getDef()->getName();
      }
    }

    // The option parameter field.
    OS << ", " << R.getValueAsInt("NumArgs");

    // The option help text.
    if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
      OS << ",\n";
      OS << "       ";
      write_cstring(OS, R.getValueAsString("HelpText"));
    } else
      OS << ", 0";

    // The option meta-variable name.
    OS << ", ";
    if (!isa<UnsetInit>(R.getValueInit("MetaVarName")))
      write_cstring(OS, R.getValueAsString("MetaVarName"));
    else
      OS << "0";

    OS << ")\n";
  }
  OS << "#endif\n";
}
} // end namespace llvm
<commit_msg>Revert "Option parsing: support case-insensitive option matching." as it broke Windows buildbot.<commit_after>//===- OptParserEmitter.cpp - Table Driven Command Line Parsing -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/TableGen/Error.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <map>

using namespace llvm;

static int StrCmpOptionName(const char *A, const char *B) {
  char a = *A, b = *B;
  while (a == b) {
    if (a == '\0')
      return 0;

    a = *++A;
    b = *++B;
  }

  if (a == '\0') // A is a prefix of B.
    return 1;
  if (b == '\0') // B is a prefix of A.
    return -1;

  // Otherwise lexicographic.
  return (a < b) ? -1 : 1;
}

static int CompareOptionRecords(const void *Av, const void *Bv) {
  const Record *A = *(const Record*const*) Av;
  const Record *B = *(const Record*const*) Bv;

  // Sentinel options precede all others and are only ordered by precedence.
  bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel");
  bool BSent = B->getValueAsDef("Kind")->getValueAsBit("Sentinel");
  if (ASent != BSent)
    return ASent ? -1 : 1;

  // Compare options by name, unless they are sentinels.
  if (!ASent)
    if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").c_str(),
                                   B->getValueAsString("Name").c_str()))
    return Cmp;

  if (!ASent) {
    std::vector<std::string> APrefixes = A->getValueAsListOfStrings("Prefixes");
    std::vector<std::string> BPrefixes = B->getValueAsListOfStrings("Prefixes");

    for (std::vector<std::string>::const_iterator APre = APrefixes.begin(),
                                                  AEPre = APrefixes.end(),
                                                  BPre = BPrefixes.begin(),
                                                  BEPre = BPrefixes.end();
                                                  APre != AEPre &&
                                                  BPre != BEPre;
                                                  ++APre, ++BPre) {
      if (int Cmp = StrCmpOptionName(APre->c_str(), BPre->c_str()))
        return Cmp;
    }
  }

  // Then by the kind precedence;
  int APrec = A->getValueAsDef("Kind")->getValueAsInt("Precedence");
  int BPrec = B->getValueAsDef("Kind")->getValueAsInt("Precedence");
  if (APrec == BPrec &&
      A->getValueAsListOfStrings("Prefixes") ==
      B->getValueAsListOfStrings("Prefixes")) {
    PrintError(A->getLoc(), Twine("Option is equivilent to"));
    PrintError(B->getLoc(), Twine("Other defined here"));
    PrintFatalError("Equivalent Options found.");
  }
  return APrec < BPrec ? -1 : 1;
}

static const std::string getOptionName(const Record &R) {
  // Use the record name unless EnumName is defined.
  if (isa<UnsetInit>(R.getValueInit("EnumName")))
    return R.getName();

  return R.getValueAsString("EnumName");
}

static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) {
  OS << '"';
  OS.write_escaped(Str);
  OS << '"';
  return OS;
}

/// OptParserEmitter - This tablegen backend takes an input .td file
/// describing a list of options and emits a data structure for parsing and
/// working with those options when given an input command line.
namespace llvm {
void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
  // Get the option groups and options.
  const std::vector<Record*> &Groups =
    Records.getAllDerivedDefinitions("OptionGroup");
  std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");

  emitSourceFileHeader("Option Parsing Definitions", OS);

  array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
  // Generate prefix groups.
  typedef SmallVector<SmallString<2>, 2> PrefixKeyT;
  typedef std::map<PrefixKeyT, std::string> PrefixesT;
  PrefixesT Prefixes;
  Prefixes.insert(std::make_pair(PrefixKeyT(), "prefix_0"));
  unsigned CurPrefix = 0;
  for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
    const Record &R = *Opts[i];
    std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes");
    PrefixKeyT prfkey(prf.begin(), prf.end());
    unsigned NewPrefix = CurPrefix + 1;
    if (Prefixes.insert(std::make_pair(prfkey, (Twine("prefix_") +
                                              Twine(NewPrefix)).str())).second)
      CurPrefix = NewPrefix;
  }

  // Dump prefixes.

  OS << "/////////\n";
  OS << "// Prefixes\n\n";
  OS << "#ifdef PREFIX\n";
  OS << "#define COMMA ,\n";
  for (PrefixesT::const_iterator I = Prefixes.begin(), E = Prefixes.end();
                                  I != E; ++I) {
    OS << "PREFIX(";

    // Prefix name.
    OS << I->second;

    // Prefix values.
    OS << ", {";
    for (PrefixKeyT::const_iterator PI = I->first.begin(),
                                    PE = I->first.end(); PI != PE; ++PI) {
      OS << "\"" << *PI << "\" COMMA ";
    }
    OS << "0})\n";
  }
  OS << "#undef COMMA\n";
  OS << "#endif\n\n";

  OS << "/////////\n";
  OS << "// Groups\n\n";
  OS << "#ifdef OPTION\n";
  for (unsigned i = 0, e = Groups.size(); i != e; ++i) {
    const Record &R = *Groups[i];

    // Start a single option entry.
    OS << "OPTION(";

    // The option prefix;
    OS << "0";

    // The option string.
    OS << ", \"" << R.getValueAsString("Name") << '"';

    // The option identifier name.
    OS  << ", "<< getOptionName(R);

    // The option kind.
    OS << ", Group";

    // The containing option group (if any).
    OS << ", ";
    if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
      OS << getOptionName(*DI->getDef());
    else
      OS << "INVALID";

    // The other option arguments (unused for groups).
    OS << ", INVALID, 0, 0, 0";

    // The option help text.
    if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
      OS << ",\n";
      OS << "       ";
      write_cstring(OS, R.getValueAsString("HelpText"));
    } else
      OS << ", 0";

    // The option meta-variable name (unused).
    OS << ", 0)\n";
  }
  OS << "\n";

  OS << "//////////\n";
  OS << "// Options\n\n";
  for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
    const Record &R = *Opts[i];

    // Start a single option entry.
    OS << "OPTION(";

    // The option prefix;
    std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes");
    OS << Prefixes[PrefixKeyT(prf.begin(), prf.end())] << ", ";

    // The option string.
    write_cstring(OS, R.getValueAsString("Name"));

    // The option identifier name.
    OS  << ", "<< getOptionName(R);

    // The option kind.
    OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");

    // The containing option group (if any).
    OS << ", ";
    if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
      OS << getOptionName(*DI->getDef());
    else
      OS << "INVALID";

    // The option alias (if any).
    OS << ", ";
    if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Alias")))
      OS << getOptionName(*DI->getDef());
    else
      OS << "INVALID";

    // The option alias arguments (if any).
    // Emitted as a \0 separated list in a string, e.g. ["foo", "bar"]
    // would become "foo\0bar\0". Note that the compiler adds an implicit
    // terminating \0 at the end.
    OS << ", ";
    std::vector<std::string> AliasArgs = R.getValueAsListOfStrings("AliasArgs");
    if (AliasArgs.size() == 0) {
      OS << "0";
    } else {
      OS << "\"";
      for (size_t i = 0, e = AliasArgs.size(); i != e; ++i)
        OS << AliasArgs[i] << "\\0";
      OS << "\"";
    }

    // The option flags.
    const ListInit *LI = R.getValueAsListInit("Flags");
    if (LI->empty()) {
      OS << ", 0";
    } else {
      OS << ", ";
      for (unsigned i = 0, e = LI->size(); i != e; ++i) {
        if (i)
          OS << " | ";
        OS << cast<DefInit>(LI->getElement(i))->getDef()->getName();
      }
    }

    // The option parameter field.
    OS << ", " << R.getValueAsInt("NumArgs");

    // The option help text.
    if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
      OS << ",\n";
      OS << "       ";
      write_cstring(OS, R.getValueAsString("HelpText"));
    } else
      OS << ", 0";

    // The option meta-variable name.
    OS << ", ";
    if (!isa<UnsetInit>(R.getValueInit("MetaVarName")))
      write_cstring(OS, R.getValueAsString("MetaVarName"));
    else
      OS << "0";

    OS << ")\n";
  }
  OS << "#endif\n";
}
} // end namespace llvm
<|endoftext|>