<commit_before>#include "Renderer.h"
#include "Camera.h" /// @todo remove this
#include "RendererInitializer.h"
#include "Material.h"
#include "App.h"

//======================================================================================================================
// Statics                                                                                =
//======================================================================================================================
float Renderer::quadVertCoords [][2] = { {1.0, 1.0}, {0.0, 1.0}, {0.0, 0.0}, {1.0, 0.0} };
int Renderer::maxColorAtachments = -1;

//======================================================================================================================
// Constructor                                                                                =
//======================================================================================================================
Renderer::Renderer():
	width(640),
	height(480),
	ms(*this),
	is(*this),
	pps(*this),
	dbg(*this)
{
}

//======================================================================================================================
// init                                                                                =
//======================================================================================================================
void Renderer::init(const RendererInitializer& initializer)
{
	// set from the initializer
	ms.ez.enabled = initializer.ms.ez.enabled;
	is.sm.enabled = initializer.is.sm.enabled;
	is.sm.pcfEnabled = initializer.is.sm.pcfEnabled;
	is.sm.bilinearEnabled = initializer.is.sm.bilinearEnabled;
	is.sm.resolution = initializer.is.sm.resolution;
	pps.hdr.enabled = initializer.pps.hdr.enabled;
	pps.hdr.renderingQuality = initializer.pps.hdr.renderingQuality;
	pps.ssao.enabled = initializer.pps.ssao.enabled;
	pps.ssao.renderingQuality = initializer.pps.ssao.renderingQuality;
	pps.ssao.bluringQuality = initializer.pps.ssao.bluringQuality;
	dbg.enabled = initializer.dbg.enabled;
	width = initializer.width;
	height = initializer.height;

	aspectRatio = float(width)/height;

	// a few sanity checks
	if(width < 10 || height < 10)
	{
		FATAL("Incorrect width");
	}

	// init the stages. Careful with the order!!!!!!!!!!
	ms.init();
	is.init();
	pps.init();
	dbg.init();
}

//======================================================================================================================
// render                                                                                =
//======================================================================================================================
void Renderer::render(Camera& cam_)
{
	cam = &cam_;

	ms.run();
	is.run();
	pps.run();
	dbg.run();

	++framesNum;
}

//======================================================================================================================
// drawQuad                                                                                =
//======================================================================================================================
void Renderer::drawQuad(int vertCoordsUniLoc)
{
	DEBUG_ERR(vertCoordsUniLoc == -1);
	glEnableVertexAttribArray(vertCoordsUniLoc);
	glVertexAttribPointer(vertCoordsUniLoc, 2, GL_FLOAT, false, 0, quadVertCoords);
	glDrawArrays(GL_QUADS, 0, 4);
	glDisableVertexAttribArray(vertCoordsUniLoc);
}

//======================================================================================================================
// setupMaterial                                                                                =
//======================================================================================================================
void Renderer::setupMaterial(const Material& mtl, const SceneNode& sceneNode, const Camera& cam)
{
	mtl.shaderProg->bind();
	uint textureUnit = 0;

	//
	// FFP stuff
	//
	if(mtl.blends)
	{
		glEnable(GL_BLEND);
		//glDisable(GL_BLEND);
		glBlendFunc(mtl.blendingSfactor, mtl.blendingDfactor);
	}
	else
		glDisable(GL_BLEND);

	if(mtl.depthTesting)
		glEnable(GL_DEPTH_TEST);
	else
		glDisable(GL_DEPTH_TEST);

	if(mtl.wireframe)
		glPolygonMode(GL_FRONT, GL_LINE);
	else
		glPolygonMode(GL_FRONT, GL_FILL);

	//
	// calc needed matrices
	//
	Mat4 modelMat(sceneNode.getWorldTransform());
	const Mat4& projectionMat = cam.getProjectionMatrix();
	const Mat4& viewMat = cam.getViewMatrix();
	Mat4 modelViewMat;
	Mat3 normalMat;
	Mat4 modelViewProjectionMat;

	// should I calculate the modelViewMat ?
	if(mtl.stdUniVars[Material::SUV_MODELVIEW_MAT] ||
	   mtl.stdUniVars[Material::SUV_MODELVIEWPROJECTION_MAT] ||
	   mtl.stdUniVars[Material::SUV_NORMAL_MAT])
	{
		modelViewMat = Mat4::combineTransformations(viewMat, modelMat);
	}

	// set matrices
	if(mtl.stdUniVars[Material::SUV_MODEL_MAT])
		mtl.stdUniVars[Material::SUV_MODEL_MAT]->setMat4(&modelMat);

	if(mtl.stdUniVars[Material::SUV_VIEW_MAT])
		mtl.stdUniVars[Material::SUV_VIEW_MAT]->setMat4(&viewMat);

	if(mtl.stdUniVars[Material::SUV_PROJECTION_MAT])
		mtl.stdUniVars[Material::SUV_PROJECTION_MAT]->setMat4(&projectionMat);

	if(mtl.stdUniVars[Material::SUV_MODELVIEW_MAT])
		mtl.stdUniVars[Material::SUV_MODELVIEW_MAT]->setMat4(&modelViewMat);

	if(mtl.stdUniVars[Material::SUV_NORMAL_MAT])
	{
		normalMat = modelViewMat.getRotationPart();
		mtl.stdUniVars[Material::SUV_NORMAL_MAT]->setMat3(&normalMat);
	}

	if(mtl.stdUniVars[Material::SUV_MODELVIEWPROJECTION_MAT])
	{
		modelViewProjectionMat = projectionMat * modelViewMat;
		mtl.stdUniVars[Material::SUV_MODELVIEWPROJECTION_MAT]->setMat4(&modelViewProjectionMat);
	}

	//
	// FAis
	//
	if(mtl.stdUniVars[Material::SUV_MS_NORMAL_FAI])
		mtl.stdUniVars[Material::SUV_MS_NORMAL_FAI]->setTexture(ms.normalFai, textureUnit++);

	if(mtl.stdUniVars[Material::SUV_MS_DIFFUSE_FAI])
		mtl.stdUniVars[Material::SUV_MS_DIFFUSE_FAI]->setTexture(ms.diffuseFai, textureUnit++);

	if(mtl.stdUniVars[Material::SUV_MS_SPECULAR_FAI])
		mtl.stdUniVars[Material::SUV_MS_SPECULAR_FAI]->setTexture(ms.specularFai, textureUnit++);

	if(mtl.stdUniVars[Material::SUV_MS_DEPTH_FAI])
		mtl.stdUniVars[Material::SUV_MS_DEPTH_FAI]->setTexture(ms.depthFai, textureUnit++);

	if(mtl.stdUniVars[Material::SUV_IS_FAI])
		mtl.stdUniVars[Material::SUV_IS_FAI]->setTexture(is.fai, textureUnit++);

	if(mtl.stdUniVars[Material::SUV_PPS_FAI])
		mtl.stdUniVars[Material::SUV_PPS_FAI]->setTexture(pps.fai, textureUnit++);

	//
	// Other
	//
	if(mtl.stdUniVars[Material::SUV_RENDERER_SIZE])
	{
		Vec2 v(width, height);
		mtl.stdUniVars[Material::SUV_RENDERER_SIZE]->setVec2(&v);
	}

	if(mtl.stdUniVars[Material::SUV_SCENE_AMBIENT_COLOR])
	{
		Vec3 col(app->getScene()->getAmbientCol());
		mtl.stdUniVars[Material::SUV_SCENE_AMBIENT_COLOR]->setVec3(&col);
	}

	//
	// set user defined vars
	//
	for(uint i=0; i<mtl.userDefinedVars.size(); i++)
	{
		const Material::UserDefinedUniVar* udv = &mtl.userDefinedVars[i];
		switch(udv->sProgVar->getGlDataType())
		{
			// texture
			case GL_SAMPLER_2D:
				udv->sProgVar->setTexture(*udv->value.texture, textureUnit++);
				break;
			// float
			case GL_FLOAT:
				udv->sProgVar->setFloat(udv->value.float_);
				break;
			// vec2
			case GL_FLOAT_VEC2:
				udv->sProgVar->setVec2(&udv->value.vec2);
				break;
			// vec3
			case GL_FLOAT_VEC3:
				udv->sProgVar->setVec3(&udv->value.vec3);
				break;
			// vec4
			case GL_FLOAT_VEC4:
				udv->sProgVar->setVec4(&udv->value.vec4);
				break;
		}
	}
}

//======================================================================================================================
// setProjectionMatrix                                                                                =
//======================================================================================================================
void Renderer::setProjectionMatrix(const Camera& cam)
{
	glMatrixMode(GL_PROJECTION);
	loadMatrix(cam.getProjectionMatrix());
}

//======================================================================================================================
// setViewMatrix                                                                                =
//======================================================================================================================
void Renderer::setViewMatrix(const Camera& cam)
{
	glMatrixMode(GL_MODELVIEW);
	loadMatrix(cam.getViewMatrix());
}

//======================================================================================================================
// unproject                                                                                =
//======================================================================================================================
Vec3 Renderer::unproject(const Vec3& windowCoords, const Mat4& modelViewMat, const Mat4& projectionMat,
                          const int view[4])
{
	Mat4 invPm = projectionMat * modelViewMat;
	invPm.invert();

	// the vec is in NDC space meaning: -1<=vec.x<=1 -1<=vec.y<=1 -1<=vec.z<=1
	Vec4 vec;
	vec.x = (2.0*(windowCoords.x-view[0]))/view[2] - 1.0;
	vec.y = (2.0*(windowCoords.y-view[1]))/view[3] - 1.0;
	vec.z = 2.0*windowCoords.z - 1.0;
	vec.w = 1.0;

	Vec4 final = invPm * vec;
	final /= final.w;
	return Vec3(final);
}

//======================================================================================================================
// ortho                                                                                =
//======================================================================================================================
Mat4 Renderer::ortho(float left, float right, float bottom, float top, float near, float far)
{
	float difx = right-left;
	float dify = top-bottom;
	float difz = far-near;
	float tx = -(right+left) / difx;
	float ty = -(top+bottom) / dify;
	float tz = -(far+near) / difz;
	Mat4 m;

	m(0, 0) = 2.0 / difx;
	m(0, 1) = 0.0;
	m(0, 2) = 0.0;
	m(0, 3) = tx;
	m(1, 0) = 0.0;
	m(1, 1) = 2.0 / dify;
	m(1, 2) = 0.0;
	m(1, 3) = ty;
	m(2, 0) = 0.0;
	m(2, 1) = 0.0;
	m(2, 2) = -2.0 / difz;
	m(2, 3) = tz;
	m(3, 0) = 0.0;
	m(3, 1) = 0.0;
	m(3, 2) = 0.0;
	m(3, 3) = 1.0;

	return m;
}

//======================================================================================================================
// getLastError                                                                                =
//======================================================================================================================
const uchar* Renderer::getLastError()
{
	return gluErrorString(glGetError());
}

//======================================================================================================================
// printLastError                                                                                =
//======================================================================================================================
void Renderer::printLastError()
{
	GLenum errid = glGetError();
	if(errid != GL_NO_ERROR)
		ERROR("OpenGL Error: " << gluErrorString(errid));
}

<commit_msg>A hotfix (the prev rev wont compile)<commit_after>#include "Renderer.h"
#include "Camera.h" /// @todo remove this
#include "RendererInitializer.h"
#include "Material.h"
#include "App.h"
#include "Scene.h"

//======================================================================================================================
// Statics                                                                                =
//======================================================================================================================
float Renderer::quadVertCoords [][2] = { {1.0, 1.0}, {0.0, 1.0}, {0.0, 0.0}, {1.0, 0.0} };
int Renderer::maxColorAtachments = -1;

//======================================================================================================================
// Constructor                                                                                =
//======================================================================================================================
Renderer::Renderer():
	width(640),
	height(480),
	ms(*this),
	is(*this),
	pps(*this),
	dbg(*this)
{
}

//======================================================================================================================
// init                                                                                =
//======================================================================================================================
void Renderer::init(const RendererInitializer& initializer)
{
	// set from the initializer
	ms.ez.enabled = initializer.ms.ez.enabled;
	is.sm.enabled = initializer.is.sm.enabled;
	is.sm.pcfEnabled = initializer.is.sm.pcfEnabled;
	is.sm.bilinearEnabled = initializer.is.sm.bilinearEnabled;
	is.sm.resolution = initializer.is.sm.resolution;
	pps.hdr.enabled = initializer.pps.hdr.enabled;
	pps.hdr.renderingQuality = initializer.pps.hdr.renderingQuality;
	pps.ssao.enabled = initializer.pps.ssao.enabled;
	pps.ssao.renderingQuality = initializer.pps.ssao.renderingQuality;
	pps.ssao.bluringQuality = initializer.pps.ssao.bluringQuality;
	dbg.enabled = initializer.dbg.enabled;
	width = initializer.width;
	height = initializer.height;

	aspectRatio = float(width)/height;

	// a few sanity checks
	if(width < 10 || height < 10)
	{
		FATAL("Incorrect width");
	}

	// init the stages. Careful with the order!!!!!!!!!!
	ms.init();
	is.init();
	pps.init();
	dbg.init();
}

//======================================================================================================================
// render                                                                                =
//======================================================================================================================
void Renderer::render(Camera& cam_)
{
	cam = &cam_;

	ms.run();
	is.run();
	pps.run();
	dbg.run();

	++framesNum;
}

//======================================================================================================================
// drawQuad                                                                                =
//======================================================================================================================
void Renderer::drawQuad(int vertCoordsUniLoc)
{
	DEBUG_ERR(vertCoordsUniLoc == -1);
	glEnableVertexAttribArray(vertCoordsUniLoc);
	glVertexAttribPointer(vertCoordsUniLoc, 2, GL_FLOAT, false, 0, quadVertCoords);
	glDrawArrays(GL_QUADS, 0, 4);
	glDisableVertexAttribArray(vertCoordsUniLoc);
}

//======================================================================================================================
// setupMaterial                                                                                =
//======================================================================================================================
void Renderer::setupMaterial(const Material& mtl, const SceneNode& sceneNode, const Camera& cam)
{
	mtl.shaderProg->bind();
	uint textureUnit = 0;

	//
	// FFP stuff
	//
	if(mtl.blends)
	{
		glEnable(GL_BLEND);
		//glDisable(GL_BLEND);
		glBlendFunc(mtl.blendingSfactor, mtl.blendingDfactor);
	}
	else
		glDisable(GL_BLEND);

	if(mtl.depthTesting)
		glEnable(GL_DEPTH_TEST);
	else
		glDisable(GL_DEPTH_TEST);

	if(mtl.wireframe)
		glPolygonMode(GL_FRONT, GL_LINE);
	else
		glPolygonMode(GL_FRONT, GL_FILL);

	//
	// calc needed matrices
	//
	Mat4 modelMat(sceneNode.getWorldTransform());
	const Mat4& projectionMat = cam.getProjectionMatrix();
	const Mat4& viewMat = cam.getViewMatrix();
	Mat4 modelViewMat;
	Mat3 normalMat;
	Mat4 modelViewProjectionMat;

	// should I calculate the modelViewMat ?
	if(mtl.stdUniVars[Material::SUV_MODELVIEW_MAT] ||
	   mtl.stdUniVars[Material::SUV_MODELVIEWPROJECTION_MAT] ||
	   mtl.stdUniVars[Material::SUV_NORMAL_MAT])
	{
		modelViewMat = Mat4::combineTransformations(viewMat, modelMat);
	}

	// set matrices
	if(mtl.stdUniVars[Material::SUV_MODEL_MAT])
		mtl.stdUniVars[Material::SUV_MODEL_MAT]->setMat4(&modelMat);

	if(mtl.stdUniVars[Material::SUV_VIEW_MAT])
		mtl.stdUniVars[Material::SUV_VIEW_MAT]->setMat4(&viewMat);

	if(mtl.stdUniVars[Material::SUV_PROJECTION_MAT])
		mtl.stdUniVars[Material::SUV_PROJECTION_MAT]->setMat4(&projectionMat);

	if(mtl.stdUniVars[Material::SUV_MODELVIEW_MAT])
		mtl.stdUniVars[Material::SUV_MODELVIEW_MAT]->setMat4(&modelViewMat);

	if(mtl.stdUniVars[Material::SUV_NORMAL_MAT])
	{
		normalMat = modelViewMat.getRotationPart();
		mtl.stdUniVars[Material::SUV_NORMAL_MAT]->setMat3(&normalMat);
	}

	if(mtl.stdUniVars[Material::SUV_MODELVIEWPROJECTION_MAT])
	{
		modelViewProjectionMat = projectionMat * modelViewMat;
		mtl.stdUniVars[Material::SUV_MODELVIEWPROJECTION_MAT]->setMat4(&modelViewProjectionMat);
	}

	//
	// FAis
	//
	if(mtl.stdUniVars[Material::SUV_MS_NORMAL_FAI])
		mtl.stdUniVars[Material::SUV_MS_NORMAL_FAI]->setTexture(ms.normalFai, textureUnit++);

	if(mtl.stdUniVars[Material::SUV_MS_DIFFUSE_FAI])
		mtl.stdUniVars[Material::SUV_MS_DIFFUSE_FAI]->setTexture(ms.diffuseFai, textureUnit++);

	if(mtl.stdUniVars[Material::SUV_MS_SPECULAR_FAI])
		mtl.stdUniVars[Material::SUV_MS_SPECULAR_FAI]->setTexture(ms.specularFai, textureUnit++);

	if(mtl.stdUniVars[Material::SUV_MS_DEPTH_FAI])
		mtl.stdUniVars[Material::SUV_MS_DEPTH_FAI]->setTexture(ms.depthFai, textureUnit++);

	if(mtl.stdUniVars[Material::SUV_IS_FAI])
		mtl.stdUniVars[Material::SUV_IS_FAI]->setTexture(is.fai, textureUnit++);

	if(mtl.stdUniVars[Material::SUV_PPS_FAI])
		mtl.stdUniVars[Material::SUV_PPS_FAI]->setTexture(pps.fai, textureUnit++);

	//
	// Other
	//
	if(mtl.stdUniVars[Material::SUV_RENDERER_SIZE])
	{
		Vec2 v(width, height);
		mtl.stdUniVars[Material::SUV_RENDERER_SIZE]->setVec2(&v);
	}

	if(mtl.stdUniVars[Material::SUV_SCENE_AMBIENT_COLOR])
	{
		Vec3 col(app->getScene()->getAmbientCol());
		mtl.stdUniVars[Material::SUV_SCENE_AMBIENT_COLOR]->setVec3(&col);
	}

	//
	// set user defined vars
	//
	for(uint i=0; i<mtl.userDefinedVars.size(); i++)
	{
		const Material::UserDefinedUniVar* udv = &mtl.userDefinedVars[i];
		switch(udv->sProgVar->getGlDataType())
		{
			// texture
			case GL_SAMPLER_2D:
				udv->sProgVar->setTexture(*udv->value.texture, textureUnit++);
				break;
			// float
			case GL_FLOAT:
				udv->sProgVar->setFloat(udv->value.float_);
				break;
			// vec2
			case GL_FLOAT_VEC2:
				udv->sProgVar->setVec2(&udv->value.vec2);
				break;
			// vec3
			case GL_FLOAT_VEC3:
				udv->sProgVar->setVec3(&udv->value.vec3);
				break;
			// vec4
			case GL_FLOAT_VEC4:
				udv->sProgVar->setVec4(&udv->value.vec4);
				break;
		}
	}
}

//======================================================================================================================
// setProjectionMatrix                                                                                =
//======================================================================================================================
void Renderer::setProjectionMatrix(const Camera& cam)
{
	glMatrixMode(GL_PROJECTION);
	loadMatrix(cam.getProjectionMatrix());
}

//======================================================================================================================
// setViewMatrix                                                                                =
//======================================================================================================================
void Renderer::setViewMatrix(const Camera& cam)
{
	glMatrixMode(GL_MODELVIEW);
	loadMatrix(cam.getViewMatrix());
}

//======================================================================================================================
// unproject                                                                                =
//======================================================================================================================
Vec3 Renderer::unproject(const Vec3& windowCoords, const Mat4& modelViewMat, const Mat4& projectionMat,
                          const int view[4])
{
	Mat4 invPm = projectionMat * modelViewMat;
	invPm.invert();

	// the vec is in NDC space meaning: -1<=vec.x<=1 -1<=vec.y<=1 -1<=vec.z<=1
	Vec4 vec;
	vec.x = (2.0*(windowCoords.x-view[0]))/view[2] - 1.0;
	vec.y = (2.0*(windowCoords.y-view[1]))/view[3] - 1.0;
	vec.z = 2.0*windowCoords.z - 1.0;
	vec.w = 1.0;

	Vec4 final = invPm * vec;
	final /= final.w;
	return Vec3(final);
}

//======================================================================================================================
// ortho                                                                                =
//======================================================================================================================
Mat4 Renderer::ortho(float left, float right, float bottom, float top, float near, float far)
{
	float difx = right-left;
	float dify = top-bottom;
	float difz = far-near;
	float tx = -(right+left) / difx;
	float ty = -(top+bottom) / dify;
	float tz = -(far+near) / difz;
	Mat4 m;

	m(0, 0) = 2.0 / difx;
	m(0, 1) = 0.0;
	m(0, 2) = 0.0;
	m(0, 3) = tx;
	m(1, 0) = 0.0;
	m(1, 1) = 2.0 / dify;
	m(1, 2) = 0.0;
	m(1, 3) = ty;
	m(2, 0) = 0.0;
	m(2, 1) = 0.0;
	m(2, 2) = -2.0 / difz;
	m(2, 3) = tz;
	m(3, 0) = 0.0;
	m(3, 1) = 0.0;
	m(3, 2) = 0.0;
	m(3, 3) = 1.0;

	return m;
}

//======================================================================================================================
// getLastError                                                                                =
//======================================================================================================================
const uchar* Renderer::getLastError()
{
	return gluErrorString(glGetError());
}

//======================================================================================================================
// printLastError                                                                                =
//======================================================================================================================
void Renderer::printLastError()
{
	GLenum errid = glGetError();
	if(errid != GL_NO_ERROR)
		ERROR("OpenGL Error: " << gluErrorString(errid));
}

<|endoftext|>


<commit_before>//===---- BDCE.cpp - Bit-tracking dead code elimination -------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Bit-Tracking Dead Code Elimination pass. Some
// instructions (shifts, some ands, ors, etc.) kill some of their input bits.
// We track these dead bits and remove instructions that compute only these
// dead bits.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar/BDCE.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/DemandedBits.h"
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Operator.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Scalar.h"
using namespace llvm;

#define DEBUG_TYPE "bdce"

STATISTIC(NumRemoved, "Number of instructions removed (unused)");
STATISTIC(NumSimplified, "Number of instructions trivialized (dead bits)");

static bool bitTrackingDCE(Function &F, DemandedBits &DB) {
  SmallVector<Instruction*, 128> Worklist;
  bool Changed = false;
  for (Instruction &I : instructions(F)) {
    if (I.getType()->isIntegerTy() &&
        !DB.getDemandedBits(&I).getBoolValue()) {
      // For live instructions that have all dead bits, first make them dead by
      // replacing all uses with something else. Then, if they don't need to
      // remain live (because they have side effects, etc.) we can remove them.
      DEBUG(dbgs() << "BDCE: Trivializing: " << I << " (all bits dead)\n");
      // FIXME: In theory we could substitute undef here instead of zero.
      // This should be reconsidered once we settle on the semantics of
      // undef, poison, etc.
      Value *Zero = ConstantInt::get(I.getType(), 0);
      ++NumSimplified;
      I.replaceAllUsesWith(Zero);
      Changed = true;
    }
    if (!DB.isInstructionDead(&I))
      continue;

    Worklist.push_back(&I);
    I.dropAllReferences();
    Changed = true;
  }

  for (Instruction *&I : Worklist) {
    ++NumRemoved;
    I->eraseFromParent();
  }

  return Changed;
}

PreservedAnalyses BDCEPass::run(Function &F, FunctionAnalysisManager &AM) {
  auto &DB = AM.getResult<DemandedBitsAnalysis>(F);
  if (bitTrackingDCE(F, DB))
    return PreservedAnalyses::none();
  return PreservedAnalyses::all();
}

namespace {
struct BDCELegacyPass : public FunctionPass {
  static char ID; // Pass identification, replacement for typeid
  BDCELegacyPass() : FunctionPass(ID) {
    initializeBDCELegacyPassPass(*PassRegistry::getPassRegistry());
  }

  bool runOnFunction(Function &F) override {
    if (skipFunction(F))
      return false;
    auto &DB = getAnalysis<DemandedBitsWrapperPass>().getDemandedBits();
    return bitTrackingDCE(F, DB);
  }

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.setPreservesCFG();
    AU.addRequired<DemandedBitsWrapperPass>();
    AU.addPreserved<GlobalsAAWrapperPass>();
  }
};
}

char BDCELegacyPass::ID = 0;
INITIALIZE_PASS_BEGIN(BDCELegacyPass, "bdce",
                      "Bit-Tracking Dead Code Elimination", false, false)
INITIALIZE_PASS_DEPENDENCY(DemandedBitsWrapperPass)
INITIALIZE_PASS_END(BDCELegacyPass, "bdce",
                    "Bit-Tracking Dead Code Elimination", false, false)

FunctionPass *llvm::createBitTrackingDCEPass() { return new BDCELegacyPass(); }
<commit_msg>[PM] BDCE: Fix caching of analyses.<commit_after>//===---- BDCE.cpp - Bit-tracking dead code elimination -------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Bit-Tracking Dead Code Elimination pass. Some
// instructions (shifts, some ands, ors, etc.) kill some of their input bits.
// We track these dead bits and remove instructions that compute only these
// dead bits.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar/BDCE.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/DemandedBits.h"
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Operator.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Scalar.h"
using namespace llvm;

#define DEBUG_TYPE "bdce"

STATISTIC(NumRemoved, "Number of instructions removed (unused)");
STATISTIC(NumSimplified, "Number of instructions trivialized (dead bits)");

static bool bitTrackingDCE(Function &F, DemandedBits &DB) {
  SmallVector<Instruction*, 128> Worklist;
  bool Changed = false;
  for (Instruction &I : instructions(F)) {
    if (I.getType()->isIntegerTy() &&
        !DB.getDemandedBits(&I).getBoolValue()) {
      // For live instructions that have all dead bits, first make them dead by
      // replacing all uses with something else. Then, if they don't need to
      // remain live (because they have side effects, etc.) we can remove them.
      DEBUG(dbgs() << "BDCE: Trivializing: " << I << " (all bits dead)\n");
      // FIXME: In theory we could substitute undef here instead of zero.
      // This should be reconsidered once we settle on the semantics of
      // undef, poison, etc.
      Value *Zero = ConstantInt::get(I.getType(), 0);
      ++NumSimplified;
      I.replaceAllUsesWith(Zero);
      Changed = true;
    }
    if (!DB.isInstructionDead(&I))
      continue;

    Worklist.push_back(&I);
    I.dropAllReferences();
    Changed = true;
  }

  for (Instruction *&I : Worklist) {
    ++NumRemoved;
    I->eraseFromParent();
  }

  return Changed;
}

PreservedAnalyses BDCEPass::run(Function &F, FunctionAnalysisManager &AM) {
  auto &DB = AM.getResult<DemandedBitsAnalysis>(F);
  if (!bitTrackingDCE(F, DB))
    return PreservedAnalyses::all();

  // FIXME: BDCE should also 'preserve the CFG'.
  // The new pass manager has currently no way to do it.
  auto PA = PreservedAnalyses();
  PA.preserve<GlobalsAA>();
  return PA;
}

namespace {
struct BDCELegacyPass : public FunctionPass {
  static char ID; // Pass identification, replacement for typeid
  BDCELegacyPass() : FunctionPass(ID) {
    initializeBDCELegacyPassPass(*PassRegistry::getPassRegistry());
  }

  bool runOnFunction(Function &F) override {
    if (skipFunction(F))
      return false;
    auto &DB = getAnalysis<DemandedBitsWrapperPass>().getDemandedBits();
    return bitTrackingDCE(F, DB);
  }

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.setPreservesCFG();
    AU.addRequired<DemandedBitsWrapperPass>();
    AU.addPreserved<GlobalsAAWrapperPass>();
  }
};
}

char BDCELegacyPass::ID = 0;
INITIALIZE_PASS_BEGIN(BDCELegacyPass, "bdce",
                      "Bit-Tracking Dead Code Elimination", false, false)
INITIALIZE_PASS_DEPENDENCY(DemandedBitsWrapperPass)
INITIALIZE_PASS_END(BDCELegacyPass, "bdce",
                    "Bit-Tracking Dead Code Elimination", false, false)

FunctionPass *llvm::createBitTrackingDCEPass() { return new BDCELegacyPass(); }
<|endoftext|>


<commit_before>/**
 * Clever programming language
 * Copyright (c) 2011-2012 Clever Team
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

#include <cstdlib>
#include <vector>
#include <unistd.h>
#include "compiler/clever.h"
#include "compiler/compiler.h"
#include "compiler/cached_ptrs.h"
#include "interpreter/ast.h"
#include "types/nativetypes.h"
#include "types/type.h"
#include "interpreter/astvisitor.h"
#include "interpreter/driver.h"
#include "interpreter/ast.h"

namespace clever {

PackageManager g_pkgmanager;

Type* CLEVER_INT_VAR    = NULL;
Type* CLEVER_DOUBLE_VAR = NULL;
Type* CLEVER_STR_VAR    = NULL;
Type* CLEVER_BOOL_VAR   = NULL;
Type* CLEVER_BYTE_VAR   = NULL;
Type* CLEVER_ARRAY_VAR  = NULL;
Type* CLEVER_MAP_VAR    = NULL;
Type* CLEVER_OBJ_VAR    = NULL;

// Set the default error level
Compiler::Error Compiler::m_error_level = Compiler::ALL;

// Set the stream to be used on error message
std::ostream& Compiler::m_error_stream  = std::cout;

jmp_buf Compiler::failure;

// Cached pointers
const CString* g_cache_ptrs[NUM_CACHED_PTRS];

/**
 * Deallocs memory used by compiler data
 */
Compiler::~Compiler() {
	if (m_ast) {
		delete m_ast;
	}

	g_scope.clear();

	if (m_initialized) {
		g_pkgmanager.shutdown();
	}
	delete g_cstring_tbl;
}

/**
 * Initializes the compiler data
 */
void Compiler::init() {
	if (!m_initialized) {
		/* Load package list */
		g_pkgmanager.init();

		/* Load the primitive data types */
		loadNativeTypes();
	}

	m_initialized = true;
}

/**
 * Shutdown compiler on error
 */
void Compiler::shutdown() {
	m_cgvisitor.shutdown();
	m_ast->clear();
}

/**
 * Loads the class representations of native types
 */
void Compiler::loadNativeTypes() {
	CLEVER_OBJECT = new Object;
	CLEVER_INT    = new Integer;
	CLEVER_STR    = new String;
	CLEVER_DOUBLE = new Double;
	CLEVER_BOOL   = new Bool;
	CLEVER_BYTE   = new Char;

	// Virtual Standard Template Types
	CLEVER_ARRAY       = new Array;
	CLEVER_MAP         = new Map;
	Type* pair         = new Pair;
	Type* function     = new FunctionType;
	Type* fwd_iterator = new ForwardIterator;
	Type* bid_iterator = new BidirectionalIterator;

	// Registers all native data types
	g_scope.pushType(CSTRING("Object"), CLEVER_OBJECT);
	g_scope.pushType(CSTRING("Int"),    CLEVER_INT);
	g_scope.pushType(CSTRING("Double"), CLEVER_DOUBLE);
	g_scope.pushType(CSTRING("String"), CLEVER_STR);
	g_scope.pushType(CSTRING("Bool"),   CLEVER_BOOL);
	g_scope.pushType(CSTRING("Byte"),   CLEVER_BYTE);
	g_scope.pushType(CSTRING("Array"),  CLEVER_ARRAY);
	g_scope.pushType(CSTRING("Map"),    CLEVER_MAP);
	g_scope.pushType(CSTRING("Pair"),   pair);
	g_scope.pushType(CSTRING("Function"), function);
	g_scope.pushType(CSTRING("ForwardIterator"), fwd_iterator);
	g_scope.pushType(CSTRING("BidirectionalIterator"), bid_iterator);

	// Initialize native data types
	CLEVER_INT->init();
	CLEVER_DOUBLE->init();
	CLEVER_STR->init();
	CLEVER_BOOL->init();
	CLEVER_BYTE->init();
	CLEVER_ARRAY->init();
	CLEVER_MAP->init();
	CLEVER_OBJECT->init();
	pair->init();
	function->init();
	fwd_iterator->init();
	bid_iterator->init();
}

/**
 * Make the visitor traverse accross the AST tree, doing the
 * typechecking, and generating the intermediate representation.
 * On error, Compiler::shutdown() will be called via longjmp.
 */
void Compiler::buildIR() {
	m_cgvisitor.init();

	// Make the visitor traverse across the AST tree
	m_ast->acceptVisitor(m_tcvisitor);
	m_ast->acceptVisitor(m_cgvisitor);

	m_cgvisitor.shutdown();

	// If used -d option in command-line, display the generated opcodes
	if (m_cgvisitor.isOpcodeDump()) {
		dumpOpcodes();
	}

	m_ast->clear();
}

/**
 * Direct the driver to parser a new file and return its AST tree
 * to be appended to the main tree
 */
ast::UnscopedBlockNode* Compiler::importFile(Driver& driver,
	const CString* file, ast::Identifier* alias) {

	if (driver.getFile() == file) {
		Compiler::warningf("Recursive import of file `%S' detected!",
			file);
		return new ast::UnscopedBlockNode;
	}

	std::string cur_file = driver.getFile()->str();

	// Get the current dirname
	cur_file.erase(
		std::find(cur_file.rbegin(), cur_file.rend(), '/').base(),
		cur_file.end());

	chdir(cur_file.c_str());

	driver.parseFile(file->str());

	return new ast::UnscopedBlockNode(alias,
		static_cast<ast::BlockNode*>(getAST()));
}

void Compiler::dumpOpcodes() {
	const OpcodeList& opcodes = m_cgvisitor.getOpcodes();
	size_t i = 0, size = opcodes.size();

	while (i < size) {
		opcodes[i]->dump();
		++i;
	}
}

/**
 * Displays an error message
 */
void Compiler::error(const std::string& message, const location& loc) {
	if (loc.begin.filename) {
		m_error_stream << "Compile error: " << message << " on "
			<< *loc.begin.filename << " line " << loc.begin.line << "\n";
	} else {
		m_error_stream << "Compile error: " << message << " on line "
			<< loc.begin.line << "\n";
	}

	// Abort the compilation
	CLEVER_ERROR_EXIT_ACTION();
}

/**
 * Displays an error message and abort the compilation
 */
void Compiler::error(const std::string& message) {
	m_error_stream << "Compile error: " << message << "\n";

	// Abort the compilation
	CLEVER_ERROR_EXIT_ACTION();
}

/**
 * Displays a formatted error message and abort the compilation
 */
void Compiler::errorf(const location& loc, const char* format, ...) {
	std::ostringstream* out = new std::ostringstream;
	va_list args;

	va_start(args, format);

	vsprintf(*out, format, args);

	va_end(args);

	error(out->str(), loc);

	delete out;

	// Abort the compilation
	CLEVER_ERROR_EXIT_ACTION();
}

/**
 * Displays an warning message
 */
void Compiler::warning(const std::string& message) {
	if (!(m_error_level & Compiler::WARNING)) {
		return;
	}

	m_error_stream << "Warning: " << message << "\n";
}

/**
 * Displays a formatted warning message
 */
void Compiler::warningf(const char* format, ...) {
	std::ostringstream out;
	va_list args;

	va_start(args, format);

	vsprintf(out, format, args);

	va_end(args);

	warning(out.str());
}

} // clever
<commit_msg>Fixed build on MSVC<commit_after>/**
 * Clever programming language
 * Copyright (c) 2011-2012 Clever Team
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

#include <cstdlib>
#include <vector>
#ifndef CLEVER_MSVC
# include <unistd.h>
#else
# include <direct.h>
#endif
#include "compiler/clever.h"
#include "compiler/compiler.h"
#include "compiler/cached_ptrs.h"
#include "interpreter/ast.h"
#include "types/nativetypes.h"
#include "types/type.h"
#include "interpreter/astvisitor.h"
#include "interpreter/driver.h"
#include "interpreter/ast.h"

namespace clever {

PackageManager g_pkgmanager;

Type* CLEVER_INT_VAR    = NULL;
Type* CLEVER_DOUBLE_VAR = NULL;
Type* CLEVER_STR_VAR    = NULL;
Type* CLEVER_BOOL_VAR   = NULL;
Type* CLEVER_BYTE_VAR   = NULL;
Type* CLEVER_ARRAY_VAR  = NULL;
Type* CLEVER_MAP_VAR    = NULL;
Type* CLEVER_OBJ_VAR    = NULL;

// Set the default error level
Compiler::Error Compiler::m_error_level = Compiler::ALL;

// Set the stream to be used on error message
std::ostream& Compiler::m_error_stream  = std::cout;

jmp_buf Compiler::failure;

// Cached pointers
const CString* g_cache_ptrs[NUM_CACHED_PTRS];

/**
 * Deallocs memory used by compiler data
 */
Compiler::~Compiler() {
	if (m_ast) {
		delete m_ast;
	}

	g_scope.clear();

	if (m_initialized) {
		g_pkgmanager.shutdown();
	}
	delete g_cstring_tbl;
}

/**
 * Initializes the compiler data
 */
void Compiler::init() {
	if (!m_initialized) {
		/* Load package list */
		g_pkgmanager.init();

		/* Load the primitive data types */
		loadNativeTypes();
	}

	m_initialized = true;
}

/**
 * Shutdown compiler on error
 */
void Compiler::shutdown() {
	m_cgvisitor.shutdown();
	m_ast->clear();
}

/**
 * Loads the class representations of native types
 */
void Compiler::loadNativeTypes() {
	CLEVER_OBJECT = new Object;
	CLEVER_INT    = new Integer;
	CLEVER_STR    = new String;
	CLEVER_DOUBLE = new Double;
	CLEVER_BOOL   = new Bool;
	CLEVER_BYTE   = new Char;

	// Virtual Standard Template Types
	CLEVER_ARRAY       = new Array;
	CLEVER_MAP         = new Map;
	Type* pair         = new Pair;
	Type* function     = new FunctionType;
	Type* fwd_iterator = new ForwardIterator;
	Type* bid_iterator = new BidirectionalIterator;

	// Registers all native data types
	g_scope.pushType(CSTRING("Object"), CLEVER_OBJECT);
	g_scope.pushType(CSTRING("Int"),    CLEVER_INT);
	g_scope.pushType(CSTRING("Double"), CLEVER_DOUBLE);
	g_scope.pushType(CSTRING("String"), CLEVER_STR);
	g_scope.pushType(CSTRING("Bool"),   CLEVER_BOOL);
	g_scope.pushType(CSTRING("Byte"),   CLEVER_BYTE);
	g_scope.pushType(CSTRING("Array"),  CLEVER_ARRAY);
	g_scope.pushType(CSTRING("Map"),    CLEVER_MAP);
	g_scope.pushType(CSTRING("Pair"),   pair);
	g_scope.pushType(CSTRING("Function"), function);
	g_scope.pushType(CSTRING("ForwardIterator"), fwd_iterator);
	g_scope.pushType(CSTRING("BidirectionalIterator"), bid_iterator);

	// Initialize native data types
	CLEVER_INT->init();
	CLEVER_DOUBLE->init();
	CLEVER_STR->init();
	CLEVER_BOOL->init();
	CLEVER_BYTE->init();
	CLEVER_ARRAY->init();
	CLEVER_MAP->init();
	CLEVER_OBJECT->init();
	pair->init();
	function->init();
	fwd_iterator->init();
	bid_iterator->init();
}

/**
 * Make the visitor traverse accross the AST tree, doing the
 * typechecking, and generating the intermediate representation.
 * On error, Compiler::shutdown() will be called via longjmp.
 */
void Compiler::buildIR() {
	m_cgvisitor.init();

	// Make the visitor traverse across the AST tree
	m_ast->acceptVisitor(m_tcvisitor);
	m_ast->acceptVisitor(m_cgvisitor);

	m_cgvisitor.shutdown();

	// If used -d option in command-line, display the generated opcodes
	if (m_cgvisitor.isOpcodeDump()) {
		dumpOpcodes();
	}

	m_ast->clear();
}

/**
 * Direct the driver to parser a new file and return its AST tree
 * to be appended to the main tree
 */
ast::UnscopedBlockNode* Compiler::importFile(Driver& driver,
	const CString* file, ast::Identifier* alias) {

	if (driver.getFile() == file) {
		Compiler::warningf("Recursive import of file `%S' detected!",
			file);
		return new ast::UnscopedBlockNode;
	}

	std::string cur_file = driver.getFile()->str();

	// Get the current dirname
	cur_file.erase(
		std::find(cur_file.rbegin(), cur_file.rend(), '/').base(),
		cur_file.end());

	chdir(cur_file.c_str());

	driver.parseFile(file->str());

	return new ast::UnscopedBlockNode(alias,
		static_cast<ast::BlockNode*>(getAST()));
}

void Compiler::dumpOpcodes() {
	const OpcodeList& opcodes = m_cgvisitor.getOpcodes();
	size_t i = 0, size = opcodes.size();

	while (i < size) {
		opcodes[i]->dump();
		++i;
	}
}

/**
 * Displays an error message
 */
void Compiler::error(const std::string& message, const location& loc) {
	if (loc.begin.filename) {
		m_error_stream << "Compile error: " << message << " on "
			<< *loc.begin.filename << " line " << loc.begin.line << "\n";
	} else {
		m_error_stream << "Compile error: " << message << " on line "
			<< loc.begin.line << "\n";
	}

	// Abort the compilation
	CLEVER_ERROR_EXIT_ACTION();
}

/**
 * Displays an error message and abort the compilation
 */
void Compiler::error(const std::string& message) {
	m_error_stream << "Compile error: " << message << "\n";

	// Abort the compilation
	CLEVER_ERROR_EXIT_ACTION();
}

/**
 * Displays a formatted error message and abort the compilation
 */
void Compiler::errorf(const location& loc, const char* format, ...) {
	std::ostringstream* out = new std::ostringstream;
	va_list args;

	va_start(args, format);

	vsprintf(*out, format, args);

	va_end(args);

	error(out->str(), loc);

	delete out;

	// Abort the compilation
	CLEVER_ERROR_EXIT_ACTION();
}

/**
 * Displays an warning message
 */
void Compiler::warning(const std::string& message) {
	if (!(m_error_level & Compiler::WARNING)) {
		return;
	}

	m_error_stream << "Warning: " << message << "\n";
}

/**
 * Displays a formatted warning message
 */
void Compiler::warningf(const char* format, ...) {
	std::ostringstream out;
	va_list args;

	va_start(args, format);

	vsprintf(out, format, args);

	va_end(args);

	warning(out.str());
}

} // clever
<|endoftext|>


<commit_before>/**************************************************************************
 * This file is property of and copyright by the ALICE HLT Project        *
 * All rights reserved.                                                   *
 *                                                                        *
 * Primary Authors: Markus Fasel                                          *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/
#include "AliHLTCaloDigitDataStruct.h"
#include "AliHLTCaloTriggerPatchContainerStruct.h"
#include "AliHLTCaloTriggerPatchDataStruct.h"

#include "AliHLTEMCALDefinitions.h"
#include "AliHLTEMCALGeometry.h"
#include "AliHLTEMCALTriggerMaker.h"
#include "AliHLTEMCALTriggerMakerComponent.h"

ClassImp(AliHLTEMCALTriggerMakerComponent)

//AliHLTEMCALTriggerMakerComponent gAliHLTEMCALTriggerMakerComponent;

AliHLTEMCALTriggerMakerComponent::AliHLTEMCALTriggerMakerComponent() :
AliHLTCaloProcessor(),
fTriggerMakerPtr(NULL),
fTriggerPatchPtr(NULL),
fGeometry(NULL)
{
}

AliHLTEMCALTriggerMakerComponent::~AliHLTEMCALTriggerMakerComponent() {
  if(fTriggerMakerPtr) delete fTriggerMakerPtr;
  if(fGeometry) delete fGeometry;
}

int AliHLTEMCALTriggerMakerComponent::DoEvent ( const AliHLTComponentEventData& evtData, const AliHLTComponentBlockData* blocks,
                AliHLTComponentTriggerData& trigData, AliHLTUInt8_t* outputPtr, AliHLTUInt32_t& size,
                std::vector<AliHLTComponentBlockData>& outputBlocks ){
  if(!blocks) {
    return 0;
  }

  //patch in order to skip calib events
  if(! IsDataEvent()){
    return 0;
  }

  //see header file for documentation
  UInt_t offset           = 0;
  UInt_t mysize           = 0;
  Int_t digitCount        = 0;
  Int_t ret               = 0;

  UInt_t specification = 0;

  fTriggerMakerPtr->ResetADC();

  const AliHLTComponentBlockData* iter = 0;
  AliHLTCaloDigitDataStruct *digit = NULL;

  Int_t nDigits = 0;
  for(Int_t ndx = 0; ndx < evtData.fBlockCnt; ndx++){
    iter = blocks + ndx;

    if(iter->fDataType != AliHLTEMCALDefinitions::fgkDigitDataType) {
      HLTDebug("Invalid data type received");
      continue;
    }

    specification |= iter->fSpecification;
    digit = reinterpret_cast<AliHLTCaloDigitDataStruct*>(iter->fPtr);
    nDigits = iter->fSize/sizeof(AliHLTCaloDigitDataStruct);
    HLTDebug("Block %d received %d digits", ndx, nDigits);
    for(Int_t idigit = 0; idigit < nDigits; idigit++){
      fTriggerMakerPtr->AddDigit(digit);
      digit++;
    }
  }

  fTriggerMakerPtr->SetTriggerPatchDataPtr(reinterpret_cast<AliHLTCaloTriggerPatchDataStruct *>(outputPtr));
  Int_t npatches = fTriggerMakerPtr->FindPatches(size);
  HLTDebug("Found %d patches", npatches);

  if(mysize != 0){
    AliHLTComponentBlockData bd;
    FillBlockData( bd );
    bd.fOffset = offset;
    bd.fSize = mysize;
    bd.fDataType = AliHLTEMCALDefinitions::fgkTriggerPatchDataType;
    bd.fSpecification = specification;
    outputBlocks.push_back(bd);
  }
  size = mysize;
  return 0;
}

const char* AliHLTEMCALTriggerMakerComponent::GetComponentID(){
  //See headerfile for documentation
  return "EmcalTriggerMaker";
}

void AliHLTEMCALTriggerMakerComponent::GetInputDataTypes(std::vector<AliHLTComponentDataType>& list){
  list.clear();
  list.push_back(AliHLTEMCALDefinitions::fgkDigitDataType);
}

AliHLTComponentDataType AliHLTEMCALTriggerMakerComponent::GetOutputDataType(){
  return AliHLTEMCALDefinitions::fgkTriggerPatchDataType;
}

void AliHLTEMCALTriggerMakerComponent::GetOutputDataSize ( unsigned long& constBase, double& inputMultiplier ){
  constBase = 1000 *(float)sizeof(AliHLTCaloTriggerPatchDataStruct);
  inputMultiplier = 0; // (float)sizeof(AliHLTCaloTriggerPatchDataStruct)/sizeof(AliHLTCaloDigitDataStruct)+1;
}

AliHLTComponent* AliHLTEMCALTriggerMakerComponent::Spawn(){
  return new AliHLTEMCALTriggerMakerComponent();
}

int AliHLTEMCALTriggerMakerComponent::DoInit ( int argc, const char** argv ){
  InitialiseGeometry();
  fTriggerMakerPtr = new AliHLTEMCALTriggerMaker;
  fTriggerMakerPtr->Initialise(fGeometry);
  return 0;
}

int AliHLTEMCALTriggerMakerComponent::Deinit(){
  if(fTriggerMakerPtr){
    delete fTriggerMakerPtr;
    fTriggerMakerPtr = 0;
  }
  if(fGeometry){
    delete fGeometry;
    fGeometry = 0;
  }
  return 0;
}

void AliHLTEMCALTriggerMakerComponent::InitialiseGeometry(){
  fGeometry = new AliHLTEMCALGeometry(GetRunNo());
}
<commit_msg>Bug fix: the size of the data was not set, therefore no data was posted<commit_after>/**************************************************************************
 * This file is property of and copyright by the ALICE HLT Project        *
 * All rights reserved.                                                   *
 *                                                                        *
 * Primary Authors: Markus Fasel                                          *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/
#include "AliHLTCaloDigitDataStruct.h"
#include "AliHLTCaloTriggerPatchContainerStruct.h"
#include "AliHLTCaloTriggerPatchDataStruct.h"

#include "AliHLTEMCALDefinitions.h"
#include "AliHLTEMCALGeometry.h"
#include "AliHLTEMCALTriggerMaker.h"
#include "AliHLTEMCALTriggerMakerComponent.h"

ClassImp(AliHLTEMCALTriggerMakerComponent)

//AliHLTEMCALTriggerMakerComponent gAliHLTEMCALTriggerMakerComponent;

AliHLTEMCALTriggerMakerComponent::AliHLTEMCALTriggerMakerComponent() :
AliHLTCaloProcessor(),
fTriggerMakerPtr(NULL),
fTriggerPatchPtr(NULL),
fGeometry(NULL)
{
}

AliHLTEMCALTriggerMakerComponent::~AliHLTEMCALTriggerMakerComponent() {
  if(fTriggerMakerPtr) delete fTriggerMakerPtr;
  if(fGeometry) delete fGeometry;
}

int AliHLTEMCALTriggerMakerComponent::DoEvent ( const AliHLTComponentEventData& evtData, const AliHLTComponentBlockData* blocks,
                AliHLTComponentTriggerData& trigData, AliHLTUInt8_t* outputPtr, AliHLTUInt32_t& size,
                std::vector<AliHLTComponentBlockData>& outputBlocks ){
  if(!blocks) {
    return 0;
  }

  //patch in order to skip calib events
  if(! IsDataEvent()){
    return 0;
  }

  //see header file for documentation
  UInt_t offset           = 0;
  UInt_t mysize           = 0;
  Int_t digitCount        = 0;
  Int_t ret               = 0;

  UInt_t specification = 0;

  fTriggerMakerPtr->ResetADC();

  const AliHLTComponentBlockData* iter = 0;
  AliHLTCaloDigitDataStruct *digit = NULL;

  Int_t nDigits = 0;
  for(Int_t ndx = 0; ndx < evtData.fBlockCnt; ndx++){
    iter = blocks + ndx;

    if(iter->fDataType != AliHLTEMCALDefinitions::fgkDigitDataType) {
      HLTDebug("Invalid data type received");
      continue;
    }

    specification |= iter->fSpecification;
    digit = reinterpret_cast<AliHLTCaloDigitDataStruct*>(iter->fPtr);
    nDigits = iter->fSize/sizeof(AliHLTCaloDigitDataStruct);
    HLTDebug("Block %d received %d digits", ndx, nDigits);
    for(Int_t idigit = 0; idigit < nDigits; idigit++){
      fTriggerMakerPtr->AddDigit(digit);
      digit++;
    }
  }

  fTriggerMakerPtr->SetTriggerPatchDataPtr(reinterpret_cast<AliHLTCaloTriggerPatchDataStruct *>(outputPtr));
  Int_t npatches = fTriggerMakerPtr->FindPatches(size);
  HLTDebug("Found %d patches", npatches);
  mysize = npatches*sizeof(AliHLTCaloTriggerPatchDataStruct);

  if(mysize != 0){
    AliHLTComponentBlockData bd;
    FillBlockData( bd );
    bd.fOffset = offset;
    bd.fSize = mysize;
    bd.fDataType = AliHLTEMCALDefinitions::fgkTriggerPatchDataType;
    bd.fSpecification = specification;
    outputBlocks.push_back(bd);
  }
  size = mysize;
  return 0;
}

const char* AliHLTEMCALTriggerMakerComponent::GetComponentID(){
  //See headerfile for documentation
  return "EmcalTriggerMaker";
}

void AliHLTEMCALTriggerMakerComponent::GetInputDataTypes(std::vector<AliHLTComponentDataType>& list){
  list.clear();
  list.push_back(AliHLTEMCALDefinitions::fgkDigitDataType);
}

AliHLTComponentDataType AliHLTEMCALTriggerMakerComponent::GetOutputDataType(){
  return AliHLTEMCALDefinitions::fgkTriggerPatchDataType;
}

void AliHLTEMCALTriggerMakerComponent::GetOutputDataSize ( unsigned long& constBase, double& inputMultiplier ){
  constBase = 1000 *(float)sizeof(AliHLTCaloTriggerPatchDataStruct);
  inputMultiplier = 0; // (float)sizeof(AliHLTCaloTriggerPatchDataStruct)/sizeof(AliHLTCaloDigitDataStruct)+1;
}

AliHLTComponent* AliHLTEMCALTriggerMakerComponent::Spawn(){
  return new AliHLTEMCALTriggerMakerComponent();
}

int AliHLTEMCALTriggerMakerComponent::DoInit ( int argc, const char** argv ){
  InitialiseGeometry();
  fTriggerMakerPtr = new AliHLTEMCALTriggerMaker;
  fTriggerMakerPtr->Initialise(fGeometry);
  return 0;
}

int AliHLTEMCALTriggerMakerComponent::Deinit(){
  if(fTriggerMakerPtr){
    delete fTriggerMakerPtr;
    fTriggerMakerPtr = 0;
  }
  if(fGeometry){
    delete fGeometry;
    fGeometry = 0;
  }
  return 0;
}

void AliHLTEMCALTriggerMakerComponent::InitialiseGeometry(){
  fGeometry = new AliHLTEMCALGeometry(GetRunNo());
}
<|endoftext|>


<commit_before>#include "nodetests.h"
#include "yaml-cpp/yaml.h"

namespace {
	struct TEST {
		TEST(): ok(false) {}
		TEST(bool ok_): ok(ok_) {}
		TEST(const char *error_): ok(false), error(error_) {}

		bool ok;
		std::string error;
	};
}

#define YAML_ASSERT(cond) do { if(!(cond)) return "  Assert failed: " #cond; } while(false)

namespace Test
{
	namespace Node
	{
		TEST SimpleScalar()
		{
			YAML::Node node = YAML::Node("Hello, World!");
			YAML_ASSERT(node.Type() == YAML::NodeType::Scalar);
			YAML_ASSERT(node.as<std::string>() == "Hello, World!");
			return true;
		}

		TEST IntScalar()
		{
			YAML::Node node = YAML::Node(15);
			YAML_ASSERT(node.Type() == YAML::NodeType::Scalar);
			YAML_ASSERT(node.as<int>() == 15);
			return true;
		}

		TEST SimpleAppendSequence()
		{
			YAML::Node node;
			node.append(10);
			node.append("foo");
			node.append("monkey");
			YAML_ASSERT(node.Type() == YAML::NodeType::Sequence);
			YAML_ASSERT(node.size() == 3);
			YAML_ASSERT(node[0].as<int>() == 10);
			YAML_ASSERT(node[1].as<std::string>() == "foo");
			YAML_ASSERT(node[2].as<std::string>() == "monkey");
			YAML_ASSERT(node.Type() == YAML::NodeType::Sequence);
			return true;
		}

		TEST SimpleAssignSequence()
		{
			YAML::Node node;
			node[0] = 10;
			node[1] = "foo";
			node[2] = "monkey";
			YAML_ASSERT(node.Type() == YAML::NodeType::Sequence);
			YAML_ASSERT(node.size() == 3);
			YAML_ASSERT(node[0].as<int>() == 10);
			YAML_ASSERT(node[1].as<std::string>() == "foo");
			YAML_ASSERT(node[2].as<std::string>() == "monkey");
			YAML_ASSERT(node.Type() == YAML::NodeType::Sequence);
			return true;
		}

		TEST SimpleMap()
		{
			YAML::Node node;
			node["key"] = "value";
			YAML_ASSERT(node.Type() == YAML::NodeType::Map);
			YAML_ASSERT(node["key"].as<std::string>() == "value");
			YAML_ASSERT(node.size() == 1);
			return true;
		}

		TEST MapWithUndefinedValues()
		{
			YAML::Node node;
			node["key"] = "value";
			node["undefined"];
			YAML_ASSERT(node.Type() == YAML::NodeType::Map);
			YAML_ASSERT(node["key"].as<std::string>() == "value");
			YAML_ASSERT(node.size() == 1);

			node["undefined"] = "monkey";
			YAML_ASSERT(node["undefined"].as<std::string>() == "monkey");
			YAML_ASSERT(node.size() == 2);

			return true;
		}

		TEST MapIteratorWithUndefinedValues()
		{
			YAML::Node node;
			node["key"] = "value";
			node["undefined"];

			std::size_t count = 0;
			for(YAML::const_iterator it=node.begin();it!=node.end();++it)
				count++;
			YAML_ASSERT(count == 1);
			return true;
		}

		TEST SimpleSubkeys()
		{
			YAML::Node node;
			node["device"]["udid"] = "12345";
			node["device"]["name"] = "iPhone";
			node["device"]["os"] = "4.0";
			node["username"] = "monkey";
			YAML_ASSERT(node["device"]["udid"].as<std::string>() == "12345");
			YAML_ASSERT(node["device"]["name"].as<std::string>() == "iPhone");
			YAML_ASSERT(node["device"]["os"].as<std::string>() == "4.0");
			YAML_ASSERT(node["username"].as<std::string>() == "monkey");
			return true;
		}

		TEST StdVector()
		{
			std::vector<int> primes;
			primes.push_back(2);
			primes.push_back(3);
			primes.push_back(5);
			primes.push_back(7);
			primes.push_back(11);
			primes.push_back(13);

			YAML::Node node;
			node["primes"] = primes;
			YAML_ASSERT(node["primes"].as<std::vector<int> >() == primes);
			return true;
		}

		TEST StdList()
		{
			std::list<int> primes;
			primes.push_back(2);
			primes.push_back(3);
			primes.push_back(5);
			primes.push_back(7);
			primes.push_back(11);
			primes.push_back(13);

			YAML::Node node;
			node["primes"] = primes;
			YAML_ASSERT(node["primes"].as<std::list<int> >() == primes);
			return true;
		}

		TEST StdMap()
		{
			std::map<int, int> squares;
			squares[0] = 0;
			squares[1] = 1;
			squares[2] = 4;
			squares[3] = 9;
			squares[4] = 16;

			YAML::Node node;
			node["squares"] = squares;
			YAML_ASSERT((node["squares"].as<std::map<int, int> >() == squares));
			return true;
		}

		TEST SimpleAlias()
		{
			YAML::Node node;
			node["foo"] = "value";
			node["bar"] = node["foo"];
			YAML_ASSERT(node["foo"].as<std::string>() == "value");
			YAML_ASSERT(node["bar"].as<std::string>() == "value");
			YAML_ASSERT(node["foo"] == node["bar"]);
			YAML_ASSERT(node.size() == 2);
			return true;
		}

		TEST AliasAsKey()
		{
			YAML::Node node;
			node["foo"] = "value";
			YAML::Node value = node["foo"];
			node[value] = "foo";
			YAML_ASSERT(node["foo"].as<std::string>() == "value");
			YAML_ASSERT(node[value].as<std::string>() == "foo");
			YAML_ASSERT(node["value"].as<std::string>() == "foo");
			YAML_ASSERT(node.size() == 2);
			return true;
		}
	}

	void RunNodeTest(TEST (*test)(), const std::string& name, int& passed, int& total) {
		TEST ret;
		try {
			ret = test();
		} catch(...) {
			ret.ok = false;
		}
		if(ret.ok) {
			passed++;
		} else {
			std::cout << "Node test failed: " << name << "\n";
			if(ret.error != "")
				std::cout << ret.error << "\n";
		}
		total++;
	}

	bool RunNodeTests()
	{
		int passed = 0;
		int total = 0;

		RunNodeTest(&Node::SimpleScalar, "simple scalar", passed, total);
		RunNodeTest(&Node::IntScalar, "int scalar", passed, total);
		RunNodeTest(&Node::SimpleAppendSequence, "simple append sequence", passed, total);
		RunNodeTest(&Node::SimpleAssignSequence, "simple assign sequence", passed, total);
		RunNodeTest(&Node::SimpleMap, "simple map", passed, total);
		RunNodeTest(&Node::MapWithUndefinedValues, "map with undefined values", passed, total);
		RunNodeTest(&Node::MapIteratorWithUndefinedValues, "map iterator with undefined values", passed, total);
		RunNodeTest(&Node::SimpleSubkeys, "simple subkey", passed, total);
		RunNodeTest(&Node::StdVector, "std::vector", passed, total);
		RunNodeTest(&Node::StdList, "std::list", passed, total);
		RunNodeTest(&Node::StdMap, "std::map", passed, total);
		RunNodeTest(&Node::SimpleAlias, "simple alias", passed, total);
		RunNodeTest(&Node::AliasAsKey, "alias as key", passed, total);

		std::cout << "Node tests: " << passed << "/" << total << " passed\n";
		return passed == total;
	}
}
<commit_msg>Added failing self-reference tests<commit_after>#include "nodetests.h"
#include "yaml-cpp/yaml.h"

namespace {
	struct TEST {
		TEST(): ok(false) {}
		TEST(bool ok_): ok(ok_) {}
		TEST(const char *error_): ok(false), error(error_) {}

		bool ok;
		std::string error;
	};
}

#define YAML_ASSERT(cond) do { if(!(cond)) return "  Assert failed: " #cond; } while(false)

namespace Test
{
	namespace Node
	{
		TEST SimpleScalar()
		{
			YAML::Node node = YAML::Node("Hello, World!");
			YAML_ASSERT(node.Type() == YAML::NodeType::Scalar);
			YAML_ASSERT(node.as<std::string>() == "Hello, World!");
			return true;
		}

		TEST IntScalar()
		{
			YAML::Node node = YAML::Node(15);
			YAML_ASSERT(node.Type() == YAML::NodeType::Scalar);
			YAML_ASSERT(node.as<int>() == 15);
			return true;
		}

		TEST SimpleAppendSequence()
		{
			YAML::Node node;
			node.append(10);
			node.append("foo");
			node.append("monkey");
			YAML_ASSERT(node.Type() == YAML::NodeType::Sequence);
			YAML_ASSERT(node.size() == 3);
			YAML_ASSERT(node[0].as<int>() == 10);
			YAML_ASSERT(node[1].as<std::string>() == "foo");
			YAML_ASSERT(node[2].as<std::string>() == "monkey");
			YAML_ASSERT(node.Type() == YAML::NodeType::Sequence);
			return true;
		}

		TEST SimpleAssignSequence()
		{
			YAML::Node node;
			node[0] = 10;
			node[1] = "foo";
			node[2] = "monkey";
			YAML_ASSERT(node.Type() == YAML::NodeType::Sequence);
			YAML_ASSERT(node.size() == 3);
			YAML_ASSERT(node[0].as<int>() == 10);
			YAML_ASSERT(node[1].as<std::string>() == "foo");
			YAML_ASSERT(node[2].as<std::string>() == "monkey");
			YAML_ASSERT(node.Type() == YAML::NodeType::Sequence);
			return true;
		}

		TEST SimpleMap()
		{
			YAML::Node node;
			node["key"] = "value";
			YAML_ASSERT(node.Type() == YAML::NodeType::Map);
			YAML_ASSERT(node["key"].as<std::string>() == "value");
			YAML_ASSERT(node.size() == 1);
			return true;
		}

		TEST MapWithUndefinedValues()
		{
			YAML::Node node;
			node["key"] = "value";
			node["undefined"];
			YAML_ASSERT(node.Type() == YAML::NodeType::Map);
			YAML_ASSERT(node["key"].as<std::string>() == "value");
			YAML_ASSERT(node.size() == 1);

			node["undefined"] = "monkey";
			YAML_ASSERT(node["undefined"].as<std::string>() == "monkey");
			YAML_ASSERT(node.size() == 2);

			return true;
		}

		TEST MapIteratorWithUndefinedValues()
		{
			YAML::Node node;
			node["key"] = "value";
			node["undefined"];

			std::size_t count = 0;
			for(YAML::const_iterator it=node.begin();it!=node.end();++it)
				count++;
			YAML_ASSERT(count == 1);
			return true;
		}

		TEST SimpleSubkeys()
		{
			YAML::Node node;
			node["device"]["udid"] = "12345";
			node["device"]["name"] = "iPhone";
			node["device"]["os"] = "4.0";
			node["username"] = "monkey";
			YAML_ASSERT(node["device"]["udid"].as<std::string>() == "12345");
			YAML_ASSERT(node["device"]["name"].as<std::string>() == "iPhone");
			YAML_ASSERT(node["device"]["os"].as<std::string>() == "4.0");
			YAML_ASSERT(node["username"].as<std::string>() == "monkey");
			return true;
		}

		TEST StdVector()
		{
			std::vector<int> primes;
			primes.push_back(2);
			primes.push_back(3);
			primes.push_back(5);
			primes.push_back(7);
			primes.push_back(11);
			primes.push_back(13);

			YAML::Node node;
			node["primes"] = primes;
			YAML_ASSERT(node["primes"].as<std::vector<int> >() == primes);
			return true;
		}

		TEST StdList()
		{
			std::list<int> primes;
			primes.push_back(2);
			primes.push_back(3);
			primes.push_back(5);
			primes.push_back(7);
			primes.push_back(11);
			primes.push_back(13);

			YAML::Node node;
			node["primes"] = primes;
			YAML_ASSERT(node["primes"].as<std::list<int> >() == primes);
			return true;
		}

		TEST StdMap()
		{
			std::map<int, int> squares;
			squares[0] = 0;
			squares[1] = 1;
			squares[2] = 4;
			squares[3] = 9;
			squares[4] = 16;

			YAML::Node node;
			node["squares"] = squares;
			YAML_ASSERT((node["squares"].as<std::map<int, int> >() == squares));
			return true;
		}

		TEST SimpleAlias()
		{
			YAML::Node node;
			node["foo"] = "value";
			node["bar"] = node["foo"];
			YAML_ASSERT(node["foo"].as<std::string>() == "value");
			YAML_ASSERT(node["bar"].as<std::string>() == "value");
			YAML_ASSERT(node["foo"] == node["bar"]);
			YAML_ASSERT(node.size() == 2);
			return true;
		}

		TEST AliasAsKey()
		{
			YAML::Node node;
			node["foo"] = "value";
			YAML::Node value = node["foo"];
			node[value] = "foo";
			YAML_ASSERT(node["foo"].as<std::string>() == "value");
			YAML_ASSERT(node[value].as<std::string>() == "foo");
			YAML_ASSERT(node["value"].as<std::string>() == "foo");
			YAML_ASSERT(node.size() == 2);
			return true;
		}

		TEST SelfReferenceSequence()
		{
			YAML::Node node;
			node[0] = node;
			YAML_ASSERT(node.Type() == YAML::NodeType::Sequence);
			YAML_ASSERT(node.size() == 1);
			YAML_ASSERT(node[0] == node);
			YAML_ASSERT(node[0][0] == node);
			YAML_ASSERT(node[0][0] == node[0]);
			return true;
		}

		TEST ValueSelfReferenceMap()
		{
			YAML::Node node;
			node["key"] = node;
			YAML_ASSERT(node.Type() == YAML::NodeType::Map);
			YAML_ASSERT(node.size() == 1);
			YAML_ASSERT(node["key"] == node);
			YAML_ASSERT(node["key"]["key"] == node);
			YAML_ASSERT(node["key"]["key"] == node["key"]);
			return true;
		}

		TEST KeySelfReferenceMap()
		{
			YAML::Node node;
			node[node] = "value";
			YAML_ASSERT(node.Type() == YAML::NodeType::Map);
			YAML_ASSERT(node.size() == 1);
			YAML_ASSERT(node[node].as<std::string>() == "value");
			return true;
		}

		TEST SelfReferenceMap()
		{
			YAML::Node node;
			node[node] = node;
			YAML_ASSERT(node.Type() == YAML::NodeType::Map);
			YAML_ASSERT(node.size() == 1);
			YAML_ASSERT(node[node] == node);
			YAML_ASSERT(node[node][node] == node);
			YAML_ASSERT(node[node][node] == node[node]);
			return true;
		}
	}

	void RunNodeTest(TEST (*test)(), const std::string& name, int& passed, int& total) {
		TEST ret;
		try {
			ret = test();
		} catch(...) {
			ret.ok = false;
		}
		if(ret.ok) {
			passed++;
		} else {
			std::cout << "Node test failed: " << name << "\n";
			if(ret.error != "")
				std::cout << ret.error << "\n";
		}
		total++;
	}

	bool RunNodeTests()
	{
		int passed = 0;
		int total = 0;

		RunNodeTest(&Node::SimpleScalar, "simple scalar", passed, total);
		RunNodeTest(&Node::IntScalar, "int scalar", passed, total);
		RunNodeTest(&Node::SimpleAppendSequence, "simple append sequence", passed, total);
		RunNodeTest(&Node::SimpleAssignSequence, "simple assign sequence", passed, total);
		RunNodeTest(&Node::SimpleMap, "simple map", passed, total);
		RunNodeTest(&Node::MapWithUndefinedValues, "map with undefined values", passed, total);
		RunNodeTest(&Node::MapIteratorWithUndefinedValues, "map iterator with undefined values", passed, total);
		RunNodeTest(&Node::SimpleSubkeys, "simple subkey", passed, total);
		RunNodeTest(&Node::StdVector, "std::vector", passed, total);
		RunNodeTest(&Node::StdList, "std::list", passed, total);
		RunNodeTest(&Node::StdMap, "std::map", passed, total);
		RunNodeTest(&Node::SimpleAlias, "simple alias", passed, total);
		RunNodeTest(&Node::AliasAsKey, "alias as key", passed, total);
		RunNodeTest(&Node::SelfReferenceSequence, "self reference sequence", passed, total);
		RunNodeTest(&Node::ValueSelfReferenceMap, "value self reference map", passed, total);
		RunNodeTest(&Node::KeySelfReferenceMap, "key self reference map", passed, total);
		RunNodeTest(&Node::SelfReferenceMap, "self reference map", passed, total);

		std::cout << "Node tests: " << passed << "/" << total << " passed\n";
		return passed == total;
	}
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkGDCMImageIO.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

  Portions of this code are covered under the VTK copyright.
  See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "itkGDCMImageIO.h"
#include "gdcmFile.h"
#include "gdcmHeader.h"
#include <fstream>

namespace itk
{

GDCMImageIO::GDCMImageIO()
{
//  this->SetNumberOfDimensions(2); //default
  m_ByteOrder = LittleEndian; //default
  m_FileType = Binary;  //default...always true
  m_RescaleSlope = 1.0;
  m_RescaleIntercept = 0.0;
  m_GdcmHeader = NULL;
}

GDCMImageIO::~GDCMImageIO()
{
  delete m_GdcmHeader;
}

bool GDCMImageIO::OpenGDCMFileForReading(std::ifstream& os,
                                         const char* filename)

{
  // Make sure that we have a file to
  if ( filename == "" )
    {
    itkExceptionMacro(<<"A FileName must be specified.");
    return false;
    }

  // Close file from any previous image
  if ( os.is_open() )
    {
    os.close();
    }

  // Open the new file for reading
  itkDebugMacro(<< "Initialize: opening file " << filename);

  // Actually open the file
  os.open( filename, std::ios::in | std::ios::binary );

  if ( os.fail() )
    {
    return false;
    }

  return true;
}

bool GDCMImageIO::OpenGDCMFileForWriting(std::ofstream& os,
                                         const char* filename)

{
  // Make sure that we have a file to
  if ( filename == "" )
    {
    itkExceptionMacro(<<"A FileName must be specified.");
    return false;
    }

  // Close file from any previous image
  if ( os.is_open() )
    {
    os.close();
    }

  // Open the new file for writing
  itkDebugMacro(<< "Initialize: opening file " << filename);

#ifdef __sgi
  // Create the file. This is required on some older sgi's
  std::ofstream tFile(filename,std::ios::out);
  tFile.close();
#endif

  // Actually open the file
  os.open( filename, std::ios::out | std::ios::binary );

  if( os.fail() )
    {
    itkExceptionMacro(<< "Could not open file for writing: " << filename);
    return false;
    }

  return true;
}

// This method will only test if the header looks like a
//GDCM image file.
bool GDCMImageIO::CanReadFile(const char* filename)
{
  std::ifstream file;
  char buffer[256];
  std::string fname(filename);

  if(  fname == "" )
    {
    itkDebugMacro(<<"No filename specified.");
    return false;
    }

  bool extensionFound = false;
  std::string::size_type sprPos = fname.rfind(".dcm");  //acr nema ??
  if ((sprPos != std::string::npos)
      && (sprPos == fname.length() - 4))
    {
    extensionFound = true;
    }

  if( !extensionFound )
    {
    itkDebugMacro(<<"The filename extension is not recognized");
    return false;
    }

  //Check for file existence:
  if ( ! this->OpenGDCMFileForReading(file, filename))
    {
    return false;
    }

  // Check to see if its a valid dicom file gdcm is able to parse:
  //We are parsing the header one time here:

  gdcmHeader GdcmHeader( fname );
  if (!GdcmHeader.IsReadable())
    {
    itkExceptionMacro("Gdcm cannot parse file " << filename );
    return false;
    }

  //For later : For 2d stack dicom:
  //we should not mix insoncistent on pixel type
  //GdcmHeader.GetPixelType();
  //we should not mix insoncistent on image size
  //GdcmHeader.GetXSize(); GdcmHeader.GetYSize(); GdcmHeader.GetZSize();
  //spacing:
  //GdcmHeader.GetXSpacing(); GdcmHeader.GetYSpacing(); ...
  //GdcmHeader.GetXOrigin() ...

  return true;
}

void GDCMImageIO::Read(void* buffer)
{
  std::ifstream file;

  //read header information file:
  this->InternalReadImageInformation(file);

  //Should I handle differently dicom lut ?
  //GdcmHeader.HasLUT()

  if( !this->ReadBufferAsBinary( file, buffer, this->GetImageSizeInBytes()) )
    {
    itkExceptionMacro(<<"Read failed: Wanted "
                      << this->GetImageSizeInBytes()
                      << " bytes, but read "
                      << file.gcount() << " bytes.");
    }

  if( !m_GdcmHeader )
    {
    m_GdcmHeader = new gdcmHeader( m_FileName );
    }

  gdcmFile GdcmFile( m_FileName );
  size_t size = GdcmFile.GetImageDataSize();
  //== this->GetImageSizeInComponents()
  unsigned char *Source = (unsigned char*)GdcmFile.GetImageData();
  memcpy((void*)buffer, (void*)Source, size);
  delete[] Source;

  //closing files:
  file.close();
}

void GDCMImageIO::InternalReadImageInformation(std::ifstream& file)
{
  //read header
  if ( ! this->OpenGDCMFileForReading(file, m_FileName.c_str()) )
    {
    itkExceptionMacro(<< "Cannot read requested file");
    }

  gdcmHeader GdcmHeader(m_FileName );

  // We don't need to positionate the Endian related stuff (by using
  // this->SetDataByteOrderToBigEndian() or SetDataByteOrderToLittleEndian()
  // since the reading of the file is done by gdcm.
  // But we do need to set up the data type for downstream filters:

  std::string type = GdcmHeader.GetPixelType();
  if( type == "8U")
    {
    SetPixelType(SCALAR);
    SetComponentType(UCHAR);
    }
  else if( type == "8S")
    {
    SetPixelType(SCALAR);
    SetComponentType(CHAR);
    }
  else if( type == "16U")
    {
    SetPixelType(SCALAR);
    SetComponentType(USHORT);
    }
  else if( type == "16S")
    {
    SetPixelType(SCALAR);
    SetComponentType(SHORT);
    }
  else if( type == "32U")
    {
    SetPixelType(SCALAR);
    SetComponentType(UINT);
    }
  else if( type == "32S")
    {
    SetPixelType(SCALAR);
    SetComponentType(INT);
    }
  else if ( type == "FD" )
    {
    //64 bits Double image
    SetPixelType(SCALAR);
    SetComponentType(DOUBLE);
    }
  else
    {
    itkExceptionMacro(<<"Unrecognized type:" << type);
    }

  // set values in case we don't find them
  this->SetNumberOfDimensions(2);
  m_Dimensions.resize(3); //very important
  m_Dimensions[0] = GdcmHeader.GetXSize();
  m_Dimensions[1] = GdcmHeader.GetYSize();
  m_Dimensions[2] = GdcmHeader.GetZSize();

  m_Spacing.resize(3); //very important
  m_Spacing[0] = GdcmHeader.GetXSpacing();
  m_Spacing[1] = GdcmHeader.GetYSpacing();
  // I have to figure out how to find the dimension (2 or 3) of the DICOM image:
  m_Spacing[2] = GdcmHeader.GetZSpacing();
  //m_Spacing[2] = 0;

  m_Origin.resize(3); //very important
  // Since SetNumberOfDimensions only reallocate for dim == 2
  m_Origin[0] = GdcmHeader.GetXOrigin();
  m_Origin[1] = GdcmHeader.GetYOrigin();
  m_Origin[2] = GdcmHeader.GetZOrigin();

  //For grayscale image :
  m_RescaleSlope = GdcmHeader.GetRescaleSlope();
  m_RescaleIntercept = GdcmHeader.GetRescaleIntercept();

}

void GDCMImageIO::ReadImageInformation()
{
  std::ifstream file;
  this->InternalReadImageInformation(file);
}

bool GDCMImageIO::CanWriteFile( const char* name )
{
  std::string filename = name;

  if(  filename == "" )
    {
    itkDebugMacro(<<"No filename specified.");
    return false;
    }

  bool extensionFound = false;
  std::string::size_type sprPos = filename.rfind(".dcm");
  if ((sprPos != std::string::npos)
      && (sprPos == filename.length() - 4))
    {
    extensionFound = true;
    }

  if( !extensionFound )
    {
    itkDebugMacro(<<"The filename extension is not recognized");
    return false;
    }

  return true;
}

void GDCMImageIO::WriteImageInformation()
{
}

void GDCMImageIO::Write(const void* buffer)
{
  std::ofstream file;
  if ( ! this->OpenGDCMFileForWriting(file, m_FileName.c_str()) )
    {
    return;
    }

  const unsigned long numberOfBytes = this->GetImageSizeInBytes();

  gdcmFile GdcmFile( m_GdcmHeader );
  GdcmFile.SetImageData((void*)buffer, numberOfBytes );
  GdcmFile.WriteDcmExplVR(m_FileName);

  file.close();
}

void GDCMImageIO::PrintSelf(std::ostream& os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);
  os << indent << "RescaleSlope: " << m_RescaleSlope << "\n";
  os << indent << "RescaleIntercept: " << m_RescaleIntercept << "\n";
}

} // end namespace itk
<commit_msg>ENH: Still a problem with gdcm CVS<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkGDCMImageIO.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

  Portions of this code are covered under the VTK copyright.
  See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "itkGDCMImageIO.h"
#include "gdcmFile.h"
#include "gdcmHeader.h"
#include <fstream>

namespace itk
{

GDCMImageIO::GDCMImageIO()
{
//  this->SetNumberOfDimensions(2); //default
  m_ByteOrder = LittleEndian; //default
  m_FileType = Binary;  //default...always true
  m_RescaleSlope = 1.0;
  m_RescaleIntercept = 0.0;
  m_GdcmHeader = NULL;
}

GDCMImageIO::~GDCMImageIO()
{
  delete m_GdcmHeader;
}

bool GDCMImageIO::OpenGDCMFileForReading(std::ifstream& os,
                                         const char* filename)

{
  // Make sure that we have a file to
  if ( filename == "" )
    {
    itkExceptionMacro(<<"A FileName must be specified.");
    return false;
    }

  // Close file from any previous image
  if ( os.is_open() )
    {
    os.close();
    }

  // Open the new file for reading
  itkDebugMacro(<< "Initialize: opening file " << filename);

  // Actually open the file
  os.open( filename, std::ios::in | std::ios::binary );

  if ( os.fail() )
    {
    return false;
    }

  return true;
}

bool GDCMImageIO::OpenGDCMFileForWriting(std::ofstream& os,
                                         const char* filename)

{
  // Make sure that we have a file to
  if ( filename == "" )
    {
    itkExceptionMacro(<<"A FileName must be specified.");
    return false;
    }

  // Close file from any previous image
  if ( os.is_open() )
    {
    os.close();
    }

  // Open the new file for writing
  itkDebugMacro(<< "Initialize: opening file " << filename);

#ifdef __sgi
  // Create the file. This is required on some older sgi's
  std::ofstream tFile(filename,std::ios::out);
  tFile.close();
#endif

  // Actually open the file
  os.open( filename, std::ios::out | std::ios::binary );

  if( os.fail() )
    {
    itkExceptionMacro(<< "Could not open file for writing: " << filename);
    return false;
    }

  return true;
}

// This method will only test if the header looks like a
// GDCM image file.
bool GDCMImageIO::CanReadFile(const char* filename)
{
  std::ifstream file;
  char buffer[256];
  std::string fname(filename);

  if(  fname == "" )
    {
    itkDebugMacro(<<"No filename specified.");
    return false;
    }

  bool extensionFound = false;
  std::string::size_type sprPos = fname.rfind(".dcm");  //acr nema ??
  if ((sprPos != std::string::npos)
      && (sprPos == fname.length() - 4))
    {
    extensionFound = true;
    }

  if( !extensionFound )
    {
    itkDebugMacro(<<"The filename extension is not recognized");
    return false;
    }

  //Check for file existence:
  if ( ! this->OpenGDCMFileForReading(file, filename))
    {
    return false;
    }

  // Check to see if its a valid dicom file gdcm is able to parse:
  //We are parsing the header one time here:

  gdcmHeader GdcmHeader( fname );
  if (!GdcmHeader.IsReadable())
    {
    itkExceptionMacro("Gdcm cannot parse file " << filename );
    return false;
    }

  //For later : For 2d stack dicom:
  //we should not mix insoncistent on pixel type
  //GdcmHeader.GetPixelType();
  //we should not mix insoncistent on image size
  //GdcmHeader.GetXSize(); GdcmHeader.GetYSize(); GdcmHeader.GetZSize();
  //spacing:
  //GdcmHeader.GetXSpacing(); GdcmHeader.GetYSpacing(); ...
  //GdcmHeader.GetXOrigin() ...

  return true;
}

void GDCMImageIO::Read(void* buffer)
{
  std::ifstream file;

  //read header information file:
  this->InternalReadImageInformation(file);

  //Should I handle differently dicom lut ?
  //GdcmHeader.HasLUT()

  if( !this->ReadBufferAsBinary( file, buffer, this->GetImageSizeInBytes()) )
    {
    itkExceptionMacro(<<"Read failed: Wanted "
                      << this->GetImageSizeInBytes()
                      << " bytes, but read "
                      << file.gcount() << " bytes.");
    }

  if( !m_GdcmHeader )
    {
    m_GdcmHeader = new gdcmHeader( m_FileName );
    }

  gdcmFile GdcmFile( m_FileName );
  size_t size = GdcmFile.GetImageDataSize();
  //== this->GetImageSizeInComponents()
  unsigned char *Source = (unsigned char*)GdcmFile.GetImageData();
  memcpy((void*)buffer, (void*)Source, size);
  delete[] Source;

  //closing files:
  file.close();
}

void GDCMImageIO::InternalReadImageInformation(std::ifstream& file)
{
  //read header
  if ( ! this->OpenGDCMFileForReading(file, m_FileName.c_str()) )
    {
    itkExceptionMacro(<< "Cannot read requested file");
    }

  gdcmHeader GdcmHeader(m_FileName );

  // We don't need to positionate the Endian related stuff (by using
  // this->SetDataByteOrderToBigEndian() or SetDataByteOrderToLittleEndian()
  // since the reading of the file is done by gdcm.
  // But we do need to set up the data type for downstream filters:

  std::string type = GdcmHeader.GetPixelType();
  if( type == "8U")
    {
    SetPixelType(SCALAR);
    SetComponentType(UCHAR);
    }
  else if( type == "8S")
    {
    SetPixelType(SCALAR);
    SetComponentType(CHAR);
    }
  else if( type == "16U")
    {
    SetPixelType(SCALAR);
    SetComponentType(USHORT);
    }
  else if( type == "16S")
    {
    SetPixelType(SCALAR);
    SetComponentType(SHORT);
    }
  else if( type == "32U")
    {
    SetPixelType(SCALAR);
    SetComponentType(UINT);
    }
  else if( type == "32S")
    {
    SetPixelType(SCALAR);
    SetComponentType(INT);
    }
  else if ( type == "FD" )
    {
    //64 bits Double image
    SetPixelType(SCALAR);
    SetComponentType(DOUBLE);
    }
  else
    {
    itkExceptionMacro(<<"Unrecognized type:" << type);
    }

  // set values in case we don't find them
  this->SetNumberOfDimensions(2);
  m_Dimensions.resize(3); //very important
  m_Dimensions[0] = GdcmHeader.GetXSize();
  m_Dimensions[1] = GdcmHeader.GetYSize();
  m_Dimensions[2] = GdcmHeader.GetZSize();

  m_Spacing.resize(3); //very important
  m_Spacing[0] = GdcmHeader.GetXSpacing();
  m_Spacing[1] = GdcmHeader.GetYSpacing();
  // I have to figure out how to find the dimension (2 or 3) of the DICOM image:
  m_Spacing[2] = GdcmHeader.GetZSpacing();
  //m_Spacing[2] = 0;

  m_Origin.resize(3); //very important
  // Since SetNumberOfDimensions only reallocate for dim == 2
  m_Origin[0] = GdcmHeader.GetXOrigin();
  m_Origin[1] = GdcmHeader.GetYOrigin();
  m_Origin[2] = GdcmHeader.GetZOrigin();

  //For grayscale image :
  m_RescaleSlope = GdcmHeader.GetRescaleSlope();
  m_RescaleIntercept = GdcmHeader.GetRescaleIntercept();

}

void GDCMImageIO::ReadImageInformation()
{
  std::ifstream file;
  this->InternalReadImageInformation(file);
}

bool GDCMImageIO::CanWriteFile( const char* name )
{
  std::string filename = name;

  if(  filename == "" )
    {
    itkDebugMacro(<<"No filename specified.");
    return false;
    }

  bool extensionFound = false;
  std::string::size_type sprPos = filename.rfind(".dcm");
  if ((sprPos != std::string::npos)
      && (sprPos == filename.length() - 4))
    {
    extensionFound = true;
    }

  if( !extensionFound )
    {
    itkDebugMacro(<<"The filename extension is not recognized");
    return false;
    }

  return true;
}

void GDCMImageIO::WriteImageInformation()
{
}

void GDCMImageIO::Write(const void* buffer)
{
  std::ofstream file;
  if ( ! this->OpenGDCMFileForWriting(file, m_FileName.c_str()) )
    {
    return;
    }

  const unsigned long numberOfBytes = this->GetImageSizeInBytes();

  gdcmFile GdcmFile( m_GdcmHeader );
  GdcmFile.GetImageData();  //FIXME: annoyance in gdcm
  GdcmFile.SetImageData((void*)buffer, numberOfBytes );
  GdcmFile.WriteDcmExplVR(m_FileName);

  file.close();
}

void GDCMImageIO::PrintSelf(std::ostream& os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);
  os << indent << "RescaleSlope: " << m_RescaleSlope << "\n";
  os << indent << "RescaleIntercept: " << m_RescaleIntercept << "\n";
}

} // end namespace itk
<|endoftext|>


<commit_before>/**
 * Clever programming language
 * Copyright (c) 2011-2012 Clever Team
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

#include <cstdlib>
#include "compiler/cstring.h"
#include "compiler/compiler.h"
#include "compiler/scope.h"
#include "compiler/value.h"
#include "interpreter/location.hh"

namespace clever {

/**
 * Compiler initialization phase
 */
void Compiler::init()
{
	m_scope = new Scope;
	m_scope_pool = (Scope**) calloc(10, sizeof(Scope*));
	m_value_pool = (Value**) calloc(10, sizeof(Value*));

	if (!m_scope_pool || !m_value_pool) {
		error("Out of memory!");
	}
	m_scope_pool[m_scope_id++] = m_scope;
	m_value_pool[m_value_id++] = NULL;
}

/**
 * Compiler termination phase
 */
void Compiler::end()
{
	m_ir.push_back(IR(OP_RETURN, 0));
}

/**
 * Displays an error message and exits
 */
void Compiler::error(const char* msg) const
{
	std::cout << "Compile error: " << msg << std::endl;
	exit(1);
}

/**
 * Displays an error message
 */
void Compiler::error(const std::string& message, const location& loc) const
{
	if (loc.begin.filename) {
		std::cerr << "Compile error: " << message << " on "
			<< *loc.begin.filename << " line " << loc.begin.line << "\n";
	} else {
		std::cerr << "Compile error: " << message << " on line "
			<< loc.begin.line << "\n";
	}
	exit(1);
}

/**
 * Displays a formatted error message and abort the compilation
 */
void Compiler::errorf(const location& loc, const char* format, ...) const
{
	std::ostringstream out;
	va_list args;

	va_start(args, format);

	vsprintf(out, format, args);

	va_end(args);

	error(out.str(), loc);
}

/**
 * Frees all resource used by the compiler
 */
void Compiler::shutdown()
{
	CLEVER_SAFE_DELETE(g_cstring_tbl);
	CLEVER_SAFE_DELETE(m_scope);
	free(m_scope_pool);

	for (size_t i = 0; i < m_value_id; ++i) {
		delete m_value_pool[i];
	}
	free(m_value_pool);
}

/**
 * Compiles a variable declaration
 */
void Compiler::varDeclaration(const CString* var, Value* node)
{
	if (node) {
		m_value_pool[m_value_id] = node;
	}

	m_ir.push_back(IR(OP_VAR_DECL, m_scope->push(var, m_value_id)));

	++m_value_id;
}

/**
 * Compiles a variable assignment
 */
void Compiler::assignment(const CString* var, Value* value, const location& loc)
{
	Symbol* sym = m_scope->getSymbol(var);

	if (!sym) {
		errorf(loc, "Variable `%S' cannot be found!", var);
	}

	m_value_pool[m_value_id] = value;

	m_ir.push_back(IR(OP_ASSIGN, sym->getValueId(), m_value_id));

	++m_value_id;
}

/**
 * Creates a new lexical scope
 */
void Compiler::newScope()
{
	m_scope = m_scope->newLexicalScope();
	m_scope->setId(m_scope_id);

	m_scope_pool[m_scope_id] = m_scope;

	m_ir.push_back(IR(OP_SCOPE, m_scope_id));

	++m_scope_id;
}

/**
 * Scope end marker to switch to parent scope
 */
void Compiler::endScope()
{
	m_scope = m_scope->getParent();

	m_ir.push_back(IR(OP_SCOPE, m_scope->getId()));
}

} // clever
<commit_msg>- Simplify code<commit_after>/**
 * Clever programming language
 * Copyright (c) 2011-2012 Clever Team
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

#include <cstdlib>
#include "compiler/cstring.h"
#include "compiler/compiler.h"
#include "compiler/scope.h"
#include "compiler/value.h"
#include "interpreter/location.hh"

namespace clever {

/**
 * Compiler initialization phase
 */
void Compiler::init()
{
	m_scope = new Scope;
	m_scope_pool = (Scope**) calloc(10, sizeof(Scope*));
	m_value_pool = (Value**) calloc(10, sizeof(Value*));

	if (!m_scope_pool || !m_value_pool) {
		error("Out of memory!");
	}
	m_scope_pool[m_scope_id++] = m_scope;
	m_value_pool[m_value_id++] = NULL;
}

/**
 * Compiler termination phase
 */
void Compiler::end()
{
	m_ir.push_back(IR(OP_RETURN, 0));
}

/**
 * Displays an error message and exits
 */
void Compiler::error(const char* msg) const
{
	std::cout << "Compile error: " << msg << std::endl;
	exit(1);
}

/**
 * Displays an error message
 */
void Compiler::error(const std::string& message, const location& loc) const
{
	if (loc.begin.filename) {
		std::cerr << "Compile error: " << message << " on "
			<< *loc.begin.filename << " line " << loc.begin.line << "\n";
	} else {
		std::cerr << "Compile error: " << message << " on line "
			<< loc.begin.line << "\n";
	}
	exit(1);
}

/**
 * Displays a formatted error message and abort the compilation
 */
void Compiler::errorf(const location& loc, const char* format, ...) const
{
	std::ostringstream out;
	va_list args;

	va_start(args, format);

	vsprintf(out, format, args);

	va_end(args);

	error(out.str(), loc);
}

/**
 * Frees all resource used by the compiler
 */
void Compiler::shutdown()
{
	CLEVER_SAFE_DELETE(g_cstring_tbl);
	CLEVER_SAFE_DELETE(m_scope);
	free(m_scope_pool);

	for (size_t i = 0; i < m_value_id; ++i) {
		delete m_value_pool[i];
	}
	free(m_value_pool);
}

/**
 * Compiles a variable declaration
 */
void Compiler::varDeclaration(const CString* var, Value* node)
{
	/**
	 * A null value is represented by m_value_id = 0 on value pool
	 */
	m_ir.push_back(IR(OP_VAR_DECL, m_scope->push(var, node ? m_value_id : 0)));

	if (node) {
		m_value_pool[m_value_id++] = node;
	}
}

/**
 * Compiles a variable assignment
 */
void Compiler::assignment(const CString* var, Value* value, const location& loc)
{
	Symbol* sym = m_scope->getSymbol(var);

	if (!sym) {
		errorf(loc, "Variable `%S' cannot be found!", var);
	}

	m_ir.push_back(IR(OP_ASSIGN, sym->getValueId(), m_value_id));

	m_value_pool[m_value_id++] = value;
}

/**
 * Creates a new lexical scope
 */
void Compiler::newScope()
{
	m_scope = m_scope->newLexicalScope();
	m_scope->setId(m_scope_id);

	m_scope_pool[m_scope_id] = m_scope;

	m_ir.push_back(IR(OP_SCOPE, m_scope_id));

	++m_scope_id;
}

/**
 * Scope end marker to switch to parent scope
 */
void Compiler::endScope()
{
	m_scope = m_scope->getParent();

	m_ir.push_back(IR(OP_SCOPE, m_scope->getId()));
}

} // clever
<|endoftext|>