Compare commits
2 Commits
STAN_WORK_
...
regalloc_c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c43d4984f | ||
|
|
cfe021ff88 |
134
mozilla/ef/Compiler/RegisterAllocator/BitSet.cpp
Normal file
134
mozilla/ef/Compiler/RegisterAllocator/BitSet.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "BitSet.h"
|
||||
|
||||
// Return the next bit after index set to true or -1 if none.
|
||||
//
|
||||
Int32 BitSet::nextOne(Int32 pos) const
|
||||
{
|
||||
++pos;
|
||||
|
||||
if (pos < 0 || Uint32(pos) >= universeSize)
|
||||
return -1;
|
||||
|
||||
Uint32 offset = getWordOffset(pos);
|
||||
Uint8 index = getBitOffset(pos);
|
||||
Word* ptr = &word[offset];
|
||||
Word currentWord = *ptr++ >> index;
|
||||
|
||||
if (currentWord != Word(0)) {
|
||||
while ((currentWord & Word(1)) == 0) {
|
||||
++index;
|
||||
currentWord >>= 1;
|
||||
}
|
||||
return (offset << nBitsInWordLog2) + index;
|
||||
}
|
||||
|
||||
Word* limit = &word[getSizeInWords(universeSize)];
|
||||
while (ptr < limit) {
|
||||
++offset;
|
||||
currentWord = *ptr++;
|
||||
if (currentWord != Word(0)) {
|
||||
index = 0;
|
||||
while ((currentWord & Word(1)) == 0) {
|
||||
++index;
|
||||
currentWord >>= 1;
|
||||
}
|
||||
return (offset << nBitsInWordLog2) + index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Return the next bit after index set to false or -1 if none.
|
||||
//
|
||||
Int32 BitSet::nextZero(Int32 pos) const
|
||||
{
|
||||
++pos;
|
||||
|
||||
if (pos < 0 || Uint32(pos) >= universeSize)
|
||||
return -1;
|
||||
|
||||
Uint32 offset = getWordOffset(pos);
|
||||
Uint8 index = getBitOffset(pos);
|
||||
Word* ptr = &word[offset];
|
||||
Word currentWord = *ptr++ >> index;
|
||||
|
||||
if (currentWord != Word(~0)) {
|
||||
for (; index < nBitsInWord; ++index) {
|
||||
if ((currentWord & Word(1)) == 0) {
|
||||
Int32 ret = (offset << nBitsInWordLog2) + index;
|
||||
return (Uint32(ret) < universeSize) ? ret : -1;
|
||||
}
|
||||
currentWord >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
Word* limit = &word[getSizeInWords(universeSize)];
|
||||
while (ptr < limit) {
|
||||
++offset;
|
||||
currentWord = *ptr++;
|
||||
if (currentWord != Word(~0)) {
|
||||
for (index = 0; index < nBitsInWord; ++index) {
|
||||
if ((currentWord & Word(1)) == 0) {
|
||||
Int32 ret = (offset << nBitsInWordLog2) + index;
|
||||
return (Uint32(ret) < universeSize) ? ret : -1;
|
||||
}
|
||||
currentWord >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
|
||||
// Print the set.
|
||||
//
|
||||
void BitSet::printPretty(LogModuleObject log)
|
||||
{
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("[ "));
|
||||
|
||||
for (Int32 i = firstOne(); i != -1; i = nextOne(i)) {
|
||||
Int32 currentBit = i;
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%d", currentBit));
|
||||
|
||||
Int32 nextBit = nextOne(currentBit);
|
||||
if (nextBit != currentBit + 1) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" "));
|
||||
continue;
|
||||
}
|
||||
|
||||
while ((nextBit != -1) && (nextBit == (currentBit + 1))) {
|
||||
currentBit = nextBit;
|
||||
nextBit = nextOne(nextBit);
|
||||
}
|
||||
|
||||
if (currentBit > (i+1))
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("-%d ", currentBit));
|
||||
else
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" %d ", currentBit));
|
||||
|
||||
i = currentBit;
|
||||
}
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("]\n"));
|
||||
}
|
||||
|
||||
#endif // DEBUG_LOG
|
||||
195
mozilla/ef/Compiler/RegisterAllocator/BitSet.h
Normal file
195
mozilla/ef/Compiler/RegisterAllocator/BitSet.h
Normal file
@@ -0,0 +1,195 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _BITSET_H_
|
||||
#define _BITSET_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "LogModule.h"
|
||||
#include "Pool.h"
|
||||
#include <string.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// BitSet -
|
||||
|
||||
class BitSet
|
||||
{
|
||||
private:
|
||||
|
||||
#if (PR_BITS_PER_WORD == 64)
|
||||
typedef Uint64 Word;
|
||||
#elif (PR_BITS_PER_WORD == 32)
|
||||
typedef Uint32 Word;
|
||||
#endif
|
||||
|
||||
static const nBitsInWord = PR_BITS_PER_WORD;
|
||||
static const nBytesInWord = PR_BYTES_PER_WORD;
|
||||
static const nBitsInWordLog2 = PR_BITS_PER_WORD_LOG2;
|
||||
static const nBytesInWordLog2 = PR_BYTES_PER_WORD_LOG2;
|
||||
|
||||
// Return the number of Word need to store the universe.
|
||||
static Uint32 getSizeInWords(Uint32 sizeOfUniverse) {return (sizeOfUniverse + (nBitsInWord - 1)) >> nBitsInWordLog2;}
|
||||
// Return the given element offset in its containing Word.
|
||||
static Uint32 getBitOffset(Uint32 element) {return element & (nBitsInWord - 1);}
|
||||
// Return the Word offset for the given element int the universe.
|
||||
static Uint32 getWordOffset(Uint32 element) {return element >> nBitsInWordLog2;}
|
||||
// Return the mask for the given bit index.
|
||||
static Word getMask(Uint8 index) {return Word(1) << index;}
|
||||
|
||||
private:
|
||||
|
||||
Uint32 universeSize; // Size of the universe
|
||||
Word* word; // universe memory.
|
||||
|
||||
private:
|
||||
|
||||
// No copy constructor.
|
||||
BitSet(const BitSet&);
|
||||
|
||||
// Check if the given set's universe is of the same size than this universe.
|
||||
void checkUniverseCompatibility(const BitSet& set) const {assert(set.universeSize == universeSize);}
|
||||
// Check if pos is valid for this set's universe.
|
||||
void checkMember(Int32 pos) const {assert(pos >=0 && Uint32(pos) < universeSize);}
|
||||
|
||||
public:
|
||||
|
||||
// Create a bitset of universeSize bits.
|
||||
BitSet(Pool& pool, Uint32 universeSize) : universeSize(universeSize) {word = new(pool) Word[getSizeInWords(universeSize)]; clear();}
|
||||
|
||||
// Return the size of this bitset.
|
||||
Uint32 getSize() const {return universeSize;}
|
||||
|
||||
// Clear the bitset.
|
||||
void clear() {memset(word, 0x00, getSizeInWords(universeSize) << nBytesInWordLog2);}
|
||||
// Clear the bit at index.
|
||||
void clear(Uint32 index) {checkMember(index); word[getWordOffset(index)] &= ~getMask(index);}
|
||||
// Set the bitset.
|
||||
void set() {memset(word, 0xFF, getSizeInWords(universeSize) << nBytesInWordLog2);}
|
||||
// Set the bit at index.
|
||||
void set(Uint32 index) {checkMember(index); word[getWordOffset(index)] |= getMask(index);}
|
||||
// Return true if the bit at index is set.
|
||||
bool test(Uint32 index) const {checkMember(index); return (word[getWordOffset(index)] & getMask(index)) != 0;}
|
||||
// Union with the given bitset.
|
||||
inline void or(const BitSet& set);
|
||||
// Intersection with the given bitset.
|
||||
inline void and(const BitSet& set);
|
||||
// Difference with the given bitset.
|
||||
inline void difference(const BitSet& set);
|
||||
// Copy set.
|
||||
inline BitSet& operator = (const BitSet& set);
|
||||
// Return true if the bitset are identical.
|
||||
friend bool operator == (const BitSet& set1, const BitSet& set2);
|
||||
// Return true if the bitset are different.
|
||||
friend bool operator != (const BitSet& set1, const BitSet& set2);
|
||||
|
||||
// Logical operators.
|
||||
BitSet& operator |= (const BitSet& set) {or(set); return *this;}
|
||||
BitSet& operator &= (const BitSet& set) {and(set); return *this;}
|
||||
BitSet& operator -= (const BitSet& set) {difference(set); return *this;}
|
||||
|
||||
// Return the first bit at set to true or -1 if none.
|
||||
Int32 firstOne() const {return nextOne(-1);}
|
||||
// Return the next bit after index set to true or -1 if none.
|
||||
Int32 nextOne(Int32 pos) const;
|
||||
// Return the first bit at set to false or -1 if none.
|
||||
Int32 firstZero() const {return nextZero(-1);}
|
||||
// Return the next bit after index set to false or -1 if none.
|
||||
Int32 nextZero(Int32 pos) const;
|
||||
|
||||
// Iterator to conform with the set API.
|
||||
typedef Int32 iterator;
|
||||
// Return true if the walk is ordered.
|
||||
static bool isOrdered() {return true;}
|
||||
// Return the iterator for the first element of this set.
|
||||
iterator begin() const {return firstOne();}
|
||||
// Return the next iterator.
|
||||
iterator advance(iterator pos) const {return nextOne(pos);}
|
||||
// Return true if the iterator is at the end of the set.
|
||||
bool done(iterator pos) const {return pos == -1;}
|
||||
// Return the element corresponding to the given iterator.
|
||||
Uint32 get(iterator pos) const {return pos;}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
// Print the set.
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
// Union with the given bitset.
|
||||
//
|
||||
inline void BitSet::or(const BitSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
Word* src = set.word;
|
||||
Word* dst = word;
|
||||
Word* limit = &src[getSizeInWords(universeSize)];
|
||||
|
||||
while (src < limit)
|
||||
*dst++ |= *src++;
|
||||
}
|
||||
|
||||
// Intersection with the given bitset.
|
||||
//
|
||||
inline void BitSet::and(const BitSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
Word* src = set.word;
|
||||
Word* dst = word;
|
||||
Word* limit = &src[getSizeInWords(universeSize)];
|
||||
|
||||
while (src < limit)
|
||||
*dst++ &= *src++;
|
||||
}
|
||||
|
||||
// Difference with the given bitset.
|
||||
//
|
||||
inline void BitSet::difference(const BitSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
Word* src = set.word;
|
||||
Word* dst = word;
|
||||
Word* limit = &src[getSizeInWords(universeSize)];
|
||||
|
||||
while (src < limit)
|
||||
*dst++ &= ~*src++;
|
||||
}
|
||||
|
||||
// Copy the given set into this set.
|
||||
//
|
||||
inline BitSet& BitSet::operator = (const BitSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
if (this != &set)
|
||||
memcpy(word, set.word, getSizeInWords(universeSize) << nBytesInWordLog2);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Return true if the given set is identical to this set.
|
||||
inline bool operator == (const BitSet& set1, const BitSet& set2)
|
||||
{
|
||||
set1.checkUniverseCompatibility(set2);
|
||||
|
||||
if (&set1 == &set2)
|
||||
return true;
|
||||
|
||||
return memcmp(set1.word, set2.word, BitSet::getSizeInWords(set1.universeSize) << BitSet::nBytesInWordLog2) == 0;
|
||||
}
|
||||
|
||||
inline bool operator != (const BitSet& set1, const BitSet& set2) {return !(set1 == set2);}
|
||||
|
||||
#endif // _BITSET_H
|
||||
159
mozilla/ef/Compiler/RegisterAllocator/Coalescing.h
Normal file
159
mozilla/ef/Compiler/RegisterAllocator/Coalescing.h
Normal file
@@ -0,0 +1,159 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _COALESCING_H_
|
||||
#define _COALESCING_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include "RegisterPressure.h"
|
||||
#include "InterferenceGraph.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "SparseSet.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
|
||||
#if 1
|
||||
// Performing an ultra conservative coalescing meens that when we look at
|
||||
// candidates (source,destination) for coalescing we need to make sure
|
||||
// that the combined interference of the source and destination register
|
||||
// will not exceed the total number of register available for the register
|
||||
// class.
|
||||
#define ULTRA_CONSERVATIVE_COALESCING
|
||||
#else
|
||||
// If we are not doing an ultra conservative coalescing we have to make sure
|
||||
// that the total number of neighbor whose degree is greater than the total
|
||||
// number of register is not greater than the total number of register.
|
||||
#undef ULTRA_CONSERVATIVE_COALESCING
|
||||
#endif
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct Coalescing
|
||||
{
|
||||
static bool coalesce(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool Coalescing<RegisterPressure>::coalesce(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
|
||||
// Initialize the lookup table
|
||||
//
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* newRange = new RegisterName[2 * rangeCount];
|
||||
RegisterName* coalescedRange = &newRange[rangeCount];
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
init(coalescedRange, rangeCount);
|
||||
|
||||
SparseSet interferences(pool, rangeCount);
|
||||
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
|
||||
bool removedInstructions = false;
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.lndList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
|
||||
// Walk the nodes in the loop nesting depth list.
|
||||
for (Int32 n = nNodes - 1; n >= 0; n--) {
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
|
||||
InstructionList::iterator it = instructions.begin();
|
||||
while (!instructions.done(it)) {
|
||||
Instruction& instruction = instructions.get(it);
|
||||
it = instructions.advance(it);
|
||||
|
||||
if ((instruction.getFlags() & ifCopy) != 0) {
|
||||
assert(instruction.getInstructionUseBegin() != instruction.getInstructionUseEnd() && instruction.getInstructionUseBegin()[0].isRegister());
|
||||
assert(instruction.getInstructionDefineBegin() != instruction.getInstructionDefineEnd() && instruction.getInstructionDefineBegin()[0].isRegister());
|
||||
|
||||
RegisterName source = findRoot(name2range[instruction.getInstructionUseBegin()[0].getRegisterName()], coalescedRange);
|
||||
RegisterName destination = findRoot(name2range[instruction.getInstructionDefineBegin()[0].getRegisterName()], coalescedRange);
|
||||
|
||||
if (source == destination) {
|
||||
instruction.remove();
|
||||
} else if (!iGraph.interfere(source, destination)) {
|
||||
InterferenceVector* sourceVector = iGraph.getInterferenceVector(source);
|
||||
InterferenceVector* destinationVector = iGraph.getInterferenceVector(destination);
|
||||
|
||||
#ifdef ULTRA_CONSERVATIVE_COALESCING
|
||||
interferences.clear();
|
||||
|
||||
InterferenceVector* vector;
|
||||
for (vector = sourceVector; vector != NULL; vector = vector->next) {
|
||||
RegisterName* neighbors = vector->neighbors;
|
||||
for (Uint32 i = 0; i < vector->count; i++)
|
||||
interferences.set(findRoot(neighbors[i], coalescedRange));
|
||||
}
|
||||
for (vector = destinationVector; vector != NULL; vector = vector->next) {
|
||||
RegisterName* neighbors = vector->neighbors;
|
||||
for (Uint32 i = 0; i < vector->count; i++)
|
||||
interferences.set(findRoot(neighbors[i], coalescedRange));
|
||||
}
|
||||
|
||||
Uint32 count = interferences.getSize();
|
||||
#else // ULTRA_CONSERVATIVE_COALESCING
|
||||
trespass("not implemented");
|
||||
Uint32 count = 0;
|
||||
#endif // ULTRA_CONSERVATIVE_COALESCING
|
||||
|
||||
if (count < 6 /* FIX: should get the number from the class */) {
|
||||
// Update the interferences vector.
|
||||
if (sourceVector == NULL) {
|
||||
iGraph.setInterferenceVector(source, destinationVector);
|
||||
sourceVector = destinationVector;
|
||||
} else if (destinationVector == NULL)
|
||||
iGraph.setInterferenceVector(destination, sourceVector);
|
||||
else {
|
||||
InterferenceVector* last = NULL;
|
||||
for (InterferenceVector* v = sourceVector; v != NULL; v = v->next)
|
||||
last = v;
|
||||
assert(last);
|
||||
last->next = destinationVector;
|
||||
iGraph.setInterferenceVector(destination, sourceVector);
|
||||
}
|
||||
// Update the interference matrix.
|
||||
for (InterferenceVector* v = sourceVector; v != NULL; v = v->next) {
|
||||
RegisterName* neighbors = v->neighbors;
|
||||
for (Uint32 i = 0; i < v->count; i++) {
|
||||
RegisterName neighbor = findRoot(neighbors[i], coalescedRange);
|
||||
iGraph.setInterference(neighbor, source);
|
||||
iGraph.setInterference(neighbor, destination);
|
||||
}
|
||||
}
|
||||
|
||||
instruction.remove();
|
||||
coalescedRange[source] = destination;
|
||||
removedInstructions = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerAllocator.rangeCount = compress(registerAllocator.name2range, coalescedRange, registerAllocator.nameCount, rangeCount);
|
||||
delete newRange;
|
||||
|
||||
return removedInstructions;
|
||||
}
|
||||
|
||||
#endif // _COALESCING_H_
|
||||
283
mozilla/ef/Compiler/RegisterAllocator/Coloring.cpp
Normal file
283
mozilla/ef/Compiler/RegisterAllocator/Coloring.cpp
Normal file
@@ -0,0 +1,283 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef NEW_LAURENTM_CODE
|
||||
|
||||
#include "Coloring.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "FastBitSet.h"
|
||||
#include "FastBitMatrix.h"
|
||||
#include "CpuInfo.h"
|
||||
|
||||
bool Coloring::
|
||||
assignRegisters(FastBitMatrix& interferenceMatrix)
|
||||
{
|
||||
PRUint32 *stackPtr = new(pool) PRUint32[vRegManager.count()];
|
||||
|
||||
return select(interferenceMatrix, stackPtr, simplify(interferenceMatrix, stackPtr));
|
||||
}
|
||||
|
||||
PRInt32 Coloring::
|
||||
getLowestSpillCostRegister(FastBitSet& bitset)
|
||||
{
|
||||
PRInt32 lowest = bitset.firstOne();
|
||||
if (lowest != -1)
|
||||
{
|
||||
Flt32 cost = vRegManager.getVirtualRegister(lowest).spillInfo.spillCost;
|
||||
for (PRInt32 r = bitset.nextOne(lowest); r != -1; r = bitset.nextOne(r))
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(r);
|
||||
if (!vReg.spillInfo.infiniteSpillCost && (vReg.spillInfo.spillCost < cost))
|
||||
{
|
||||
cost = vReg.spillInfo.spillCost;
|
||||
lowest = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
return lowest;
|
||||
}
|
||||
|
||||
PRUint32* Coloring::
|
||||
simplify(FastBitMatrix interferenceMatrix, PRUint32* stackPtr)
|
||||
{
|
||||
// first we construct the sets low and high. low contains all nodes of degree
|
||||
// inferior to the number of register available on the processor. All the
|
||||
// nodes with an high degree and a finite spill cost are placed in high.
|
||||
// Nodes of high degree and infinite spill cost are not included in either sets.
|
||||
|
||||
PRUint32 nRegisters = vRegManager.count();
|
||||
FastBitSet low(pool, nRegisters);
|
||||
FastBitSet high(pool, nRegisters);
|
||||
FastBitSet stack(pool, nRegisters);
|
||||
|
||||
for (VirtualRegisterManager::iterator i = vRegManager.begin(); !vRegManager.done(i); i = vRegManager.advance(i))
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(i);
|
||||
|
||||
if (vReg.getClass() == vrcStackSlot)
|
||||
{
|
||||
stack.set(i);
|
||||
vReg.colorRegister(nRegisters);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vReg.colorInfo.interferenceDegree < NUMBER_OF_REGISTERS)
|
||||
low.set(i);
|
||||
else // if (!vReg.spillInfo.infiniteSpillCost)
|
||||
high.set(i);
|
||||
|
||||
// Set coloring info.
|
||||
vReg.spillInfo.willSpill = false;
|
||||
|
||||
switch(vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
vReg.colorRegister(LAST_GREGISTER + 1);
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
vReg.colorRegister(LAST_FPREGISTER + 1);
|
||||
break;
|
||||
default:
|
||||
PR_ASSERT(false); // Cannot happen.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// push the stack registers
|
||||
PRInt32 j;
|
||||
for (j = stack.firstOne(); j != -1; j = stack.nextOne(j))
|
||||
*stackPtr++ = j;
|
||||
|
||||
// simplify
|
||||
while (true)
|
||||
{
|
||||
PRInt32 r;
|
||||
while ((r = getLowestSpillCostRegister(low)) != -1)
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(r);
|
||||
|
||||
/* update low and high */
|
||||
FastBitSet inter(interferenceMatrix.getRow(r), nRegisters);
|
||||
for (j = inter.firstOne(); j != -1; j = inter.nextOne(j))
|
||||
{
|
||||
VirtualRegister& neighbor = vRegManager.getVirtualRegister(j);
|
||||
// if the new interference degree of one of his neighbor becomes
|
||||
// NUMBER_OF_REGISTERS - 1 then it is added to the set 'low'.
|
||||
|
||||
PRUint32 maxInterference = 0;
|
||||
switch (neighbor.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
maxInterference = NUMBER_OF_GREGISTERS;
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
maxInterference = NUMBER_OF_FPREGISTERS;
|
||||
break;
|
||||
default:
|
||||
PR_ASSERT(false);
|
||||
}
|
||||
if ((vRegManager.getVirtualRegister(j).colorInfo.interferenceDegree-- == maxInterference))
|
||||
{
|
||||
high.clear(j);
|
||||
low.set(j);
|
||||
}
|
||||
vReg.colorInfo.interferenceDegree--;
|
||||
interferenceMatrix.clear(r, j);
|
||||
interferenceMatrix.clear(j, r);
|
||||
}
|
||||
low.clear(r);
|
||||
|
||||
// Push this register.
|
||||
*stackPtr++ = r;
|
||||
}
|
||||
if ((r = getLowestSpillCostRegister(high)) != -1)
|
||||
{
|
||||
high.clear(r);
|
||||
low.set(r);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return stackPtr;
|
||||
}
|
||||
|
||||
bool Coloring::
|
||||
select(FastBitMatrix& interferenceMatrix, PRUint32* stackBase, PRUint32* stackPtr)
|
||||
{
|
||||
PRUint32 nRegisters = vRegManager.count();
|
||||
FastBitSet usedRegisters(NUMBER_OF_REGISTERS + 1); // usedRegisters if used for both GR & FPR.
|
||||
FastBitSet preColoredRegisters(NUMBER_OF_REGISTERS + 1);
|
||||
FastBitSet usedStack(nRegisters + 1);
|
||||
bool success = true;
|
||||
Int32 lastUsedSSR = -1;
|
||||
|
||||
// select
|
||||
while (stackPtr != stackBase)
|
||||
{
|
||||
// Pop one register.
|
||||
PRUint32 r = *--stackPtr;
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(r);
|
||||
|
||||
FastBitSet neighbors(interferenceMatrix.getRow(r), nRegisters);
|
||||
|
||||
if (vReg.getClass() == vrcStackSlot)
|
||||
// Stack slots coloring.
|
||||
{
|
||||
usedStack.clear();
|
||||
|
||||
for (PRInt32 i = neighbors.firstOne(); i != -1; i = neighbors.nextOne(i))
|
||||
usedStack.set(vRegManager.getVirtualRegister(i).getColor());
|
||||
|
||||
Int32 color = usedStack.firstZero();
|
||||
vReg.colorRegister(color);
|
||||
if (color > lastUsedSSR)
|
||||
lastUsedSSR = color;
|
||||
}
|
||||
else
|
||||
// Integer & Floating point register coloring.
|
||||
{
|
||||
usedRegisters.clear();
|
||||
preColoredRegisters.clear();
|
||||
|
||||
for (PRInt32 i = neighbors.firstOne(); i != -1; i = neighbors.nextOne(i))
|
||||
{
|
||||
VirtualRegister& nvReg = vRegManager.getVirtualRegister(i);
|
||||
usedRegisters.set(nvReg.getColor());
|
||||
if (nvReg.isPreColored())
|
||||
preColoredRegisters.set(nvReg.getPreColor());
|
||||
}
|
||||
if (vReg.hasSpecialInterference)
|
||||
usedRegisters |= vReg.specialInterference;
|
||||
|
||||
PRInt8 c = -1;
|
||||
PRInt8 maxColor = 0;
|
||||
PRInt8 firstColor = 0;
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
firstColor = FIRST_GREGISTER;
|
||||
maxColor = LAST_GREGISTER;
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
firstColor = FIRST_FPREGISTER;
|
||||
maxColor = LAST_FPREGISTER;
|
||||
break;
|
||||
default:
|
||||
PR_ASSERT(false);
|
||||
}
|
||||
|
||||
if (vReg.isPreColored())
|
||||
{
|
||||
c = vReg.getPreColor();
|
||||
if (usedRegisters.test(c))
|
||||
c = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (c = usedRegisters.nextZero(firstColor - 1); (c >= 0) && (c <= maxColor) && (preColoredRegisters.test(c));
|
||||
c = usedRegisters.nextZero(c)) {}
|
||||
}
|
||||
|
||||
if ((c >= 0) && (c <= maxColor))
|
||||
{
|
||||
vReg.colorRegister(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
VirtualRegister& stackRegister = vRegManager.newVirtualRegister(vrcStackSlot);
|
||||
vReg.equivalentRegister[vrcStackSlot] = &stackRegister;
|
||||
vReg.spillInfo.willSpill = true;
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (success)
|
||||
{
|
||||
for (VirtualRegisterManager::iterator i = vRegManager.begin(); !vRegManager.done(i); i = vRegManager.advance(i))
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(i);
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
if (vReg.getColor() > LAST_GREGISTER)
|
||||
PR_ASSERT(false);
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
#if NUMBER_OF_FPREGISTERS != 0
|
||||
if (vReg.getColor() > LAST_FPREGISTER)
|
||||
PR_ASSERT(false);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
vRegManager.nUsedStackSlots = lastUsedSSR + 1;
|
||||
return success;
|
||||
}
|
||||
#endif // NEW_LAURENTM_CODE
|
||||
284
mozilla/ef/Compiler/RegisterAllocator/Coloring.h
Normal file
284
mozilla/ef/Compiler/RegisterAllocator/Coloring.h
Normal file
@@ -0,0 +1,284 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "InterferenceGraph.h"
|
||||
#include "SparseSet.h"
|
||||
#include "Spilling.h"
|
||||
#include "Splits.h"
|
||||
|
||||
UT_EXTERN_LOG_MODULE(RegAlloc);
|
||||
|
||||
template <class RegisterPressure>
|
||||
class Coloring
|
||||
{
|
||||
private:
|
||||
static RegisterName* simplify(RegisterAllocator& registerAllocator, RegisterName* coloringStack);
|
||||
static bool select(RegisterAllocator& registerAllocator, RegisterName* coloringStack, RegisterName* coloringStackPtr);
|
||||
|
||||
public:
|
||||
static bool color(RegisterAllocator& registerAllocator);
|
||||
static void finalColoring(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Coloring<RegisterPressure>::finalColoring(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
RegisterName* color = registerAllocator.color;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
usePtr->setRegisterName(color[name2range[usePtr->getRegisterName()]]);
|
||||
#ifdef DEBUG
|
||||
RegisterID rid = usePtr->getRegisterID();
|
||||
setColoredRegister(rid);
|
||||
usePtr->setRegisterID(rid);
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
definePtr->setRegisterName(color[name2range[definePtr->getRegisterName()]]);
|
||||
#ifdef DEBUG
|
||||
RegisterID rid = definePtr->getRegisterID();
|
||||
setColoredRegister(rid);
|
||||
definePtr->setRegisterID(rid);
|
||||
#endif // DEBUG
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool Coloring<RegisterPressure>::select(RegisterAllocator& registerAllocator, RegisterName* coloringStack, RegisterName* coloringStackPtr)
|
||||
{
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* color = new RegisterName[rangeCount];
|
||||
registerAllocator.color = color;
|
||||
|
||||
for (Uint32 r = 1; r < rangeCount; r++)
|
||||
color[r] = RegisterName(6); // FIX;
|
||||
|
||||
// Color the preColored registers.
|
||||
//
|
||||
VirtualRegisterManager& vrManager = registerAllocator.vrManager;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
PreColoredRegister* machineEnd = vrManager.getMachineRegistersEnd();
|
||||
for (PreColoredRegister* machinePtr = vrManager.getMachineRegistersBegin(); machinePtr < machineEnd; machinePtr++)
|
||||
if (machinePtr->id != invalidID) {
|
||||
color[name2range[getName(machinePtr->id)]] = machinePtr->color;
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\twill preColor range %d as %d\n", name2range[getName(machinePtr->id)], machinePtr->color));
|
||||
}
|
||||
|
||||
SpillCost* cost = registerAllocator.spillCost;
|
||||
Pool& pool = registerAllocator.pool;
|
||||
SparseSet& spill = *new(pool) SparseSet(pool, rangeCount);
|
||||
registerAllocator.willSpill = &spill;
|
||||
SparseSet neighborColors(pool, 6); // FIX
|
||||
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
|
||||
|
||||
bool coloringFailed = false;
|
||||
while (coloringStackPtr > coloringStack) {
|
||||
RegisterName range = *--coloringStackPtr;
|
||||
|
||||
if (!cost[range].infinite && cost[range].cost < 0) {
|
||||
coloringFailed = true;
|
||||
spill.set(range);
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tfailed to color %d, will spill.\n", range));
|
||||
} else {
|
||||
neighborColors.clear();
|
||||
|
||||
for (InterferenceVector* vector = iGraph.getInterferenceVector(range); vector != NULL; vector = vector->next)
|
||||
for (Int32 i = vector->count - 1; i >= 0; --i) {
|
||||
RegisterName neighborColor = color[vector->neighbors[i]];
|
||||
if (neighborColor < 6) // FIX
|
||||
neighborColors.set(neighborColor);
|
||||
}
|
||||
|
||||
if (neighborColors.getSize() == 6) { // FIX
|
||||
coloringFailed = true;
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tfailed to color %d, ", range));
|
||||
|
||||
if (!Splits<RegisterPressure>::findSplit(registerAllocator, color, range)) {
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("will spill.\n"));
|
||||
spill.set(range);
|
||||
} else
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("will split.\n"));
|
||||
} else {
|
||||
for (Uint32 i = 0; i < 6; i++) // FIX
|
||||
if (!neighborColors.test(i)) {
|
||||
fprintf(stdout, "\twill color %d as %d\n", range, i);
|
||||
color[range] = RegisterName(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
if (coloringFailed) {
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring failed:\n"));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\twill spill: "));
|
||||
spill.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
} else {
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring succeeded:\n"));
|
||||
for (Uint32 i = 1; i < rangeCount; i++)
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\trange %d colored as %d\n", i, color[i]));
|
||||
}
|
||||
#endif
|
||||
|
||||
return !coloringFailed;
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
RegisterName* Coloring<RegisterPressure>::simplify(RegisterAllocator& registerAllocator, RegisterName* coloringStack)
|
||||
{
|
||||
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
|
||||
SpillCost* spillCost = registerAllocator.spillCost;
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
|
||||
Uint32* degree = new Uint32[rangeCount];
|
||||
for (RegisterName i = RegisterName(1); i < rangeCount; i = RegisterName(i + 1)) {
|
||||
InterferenceVector* vector = iGraph.getInterferenceVector(i);
|
||||
degree[i] = (vector != NULL) ? vector->count : 0;
|
||||
}
|
||||
|
||||
Pool& pool = registerAllocator.pool;
|
||||
SparseSet low(pool, rangeCount);
|
||||
SparseSet high(pool, rangeCount);
|
||||
SparseSet highInfinite(pool, rangeCount);
|
||||
SparseSet preColored(pool, rangeCount);
|
||||
|
||||
// Get the precolored registers.
|
||||
//
|
||||
VirtualRegisterManager& vrManager = registerAllocator.vrManager;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
PreColoredRegister* machineEnd = vrManager.getMachineRegistersEnd();
|
||||
for (PreColoredRegister* machinePtr = vrManager.getMachineRegistersBegin(); machinePtr < machineEnd; machinePtr++)
|
||||
if (machinePtr->id != invalidID)
|
||||
preColored.set(name2range[getName(machinePtr->id)]);
|
||||
|
||||
// Insert the live ranges in the sets.
|
||||
//
|
||||
for (Uint32 range = 1; range < rangeCount; range++)
|
||||
if (!preColored.test(range))
|
||||
if (degree[range] < 6) // FIX
|
||||
low.set(range);
|
||||
else if (!spillCost[range].infinite)
|
||||
high.set(range);
|
||||
else
|
||||
highInfinite.set(range);
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring sets:\n\tlow = "));
|
||||
low.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\thigh = "));
|
||||
high.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\thighInfinite = "));
|
||||
highInfinite.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tpreColored = "));
|
||||
preColored.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
RegisterName* coloringStackPtr = coloringStack;
|
||||
|
||||
while (low.getSize() != 0 || high.getSize() != 0) {
|
||||
while (low.getSize() != 0) {
|
||||
RegisterName range = RegisterName(low.getOne());
|
||||
low.clear(range);
|
||||
*coloringStackPtr++ = range;
|
||||
|
||||
for (InterferenceVector* vector = iGraph.getInterferenceVector(range); vector != NULL; vector = vector->next)
|
||||
for (Int32 i = (vector->count - 1); i >= 0; --i) {
|
||||
RegisterName neighbor = vector->neighbors[i];
|
||||
degree[neighbor]--;
|
||||
|
||||
if (degree[neighbor] < 6) // FIX
|
||||
if (high.test(neighbor)) {
|
||||
high.clear(neighbor);
|
||||
low.set(neighbor);
|
||||
} else if (highInfinite.test(neighbor)) {
|
||||
highInfinite.clear(neighbor);
|
||||
low.set(neighbor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (high.getSize() != 0) {
|
||||
RegisterName best = RegisterName(high.getOne());
|
||||
double bestCost = spillCost[best].cost;
|
||||
double bestDegree = degree[best];
|
||||
|
||||
// Choose the next best candidate.
|
||||
//
|
||||
for (SparseSet::iterator i = high.begin(); !high.done(i); i = high.advance(i)) {
|
||||
RegisterName range = RegisterName(high.get(i));
|
||||
double thisCost = spillCost[range].cost;
|
||||
double thisDegree = degree[range];
|
||||
|
||||
if (thisCost * bestDegree < bestCost * thisDegree) {
|
||||
best = range;
|
||||
bestCost = thisCost;
|
||||
bestDegree = thisDegree;
|
||||
}
|
||||
}
|
||||
|
||||
high.clear(best);
|
||||
low.set(best);
|
||||
}
|
||||
}
|
||||
assert(highInfinite.getSize() == 0);
|
||||
|
||||
delete degree;
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring stack:\n\t"));
|
||||
for (RegisterName* sp = coloringStack; sp < coloringStackPtr; ++sp)
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("%d ", *sp));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\n"));
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
return coloringStackPtr;
|
||||
}
|
||||
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool Coloring<RegisterPressure>::color(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
RegisterName* coloringStack = new RegisterName[registerAllocator.rangeCount];
|
||||
return select(registerAllocator, coloringStack, simplify(registerAllocator, coloringStack));
|
||||
}
|
||||
212
mozilla/ef/Compiler/RegisterAllocator/DominatorGraph.cpp
Normal file
212
mozilla/ef/Compiler/RegisterAllocator/DominatorGraph.cpp
Normal file
@@ -0,0 +1,212 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include <string.h>
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
|
||||
#include "DominatorGraph.h"
|
||||
|
||||
DominatorGraph::DominatorGraph(ControlGraph& controlGraph) : controlGraph(controlGraph)
|
||||
{
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
GtoV = new Uint32[nNodes + 1];
|
||||
VtoG = new Uint32[nNodes + 1];
|
||||
|
||||
Uint32 v = 1;
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
VtoG[v] = n;
|
||||
GtoV[n] = v++;
|
||||
}
|
||||
|
||||
// Initialize all the 1-based arrays.
|
||||
//
|
||||
parent = new Uint32[v];
|
||||
semi = new Uint32[v];
|
||||
vertex = new Uint32[v];
|
||||
label = new Uint32[v];
|
||||
size = new Uint32[v];
|
||||
ancestor = new Uint32[v];
|
||||
child = new Uint32[v];
|
||||
dom = new Uint32[v];
|
||||
bucket = new DGLinkedList*[v];
|
||||
|
||||
memset(semi, '\0', v * sizeof(Uint32));
|
||||
memset(bucket, '\0', v * sizeof(DGLinkedList*));
|
||||
|
||||
vCount = v;
|
||||
|
||||
build();
|
||||
|
||||
delete parent;
|
||||
delete semi;
|
||||
delete vertex;
|
||||
delete label;
|
||||
delete size;
|
||||
delete ancestor;
|
||||
delete child;
|
||||
delete dom;
|
||||
delete bucket;
|
||||
}
|
||||
|
||||
Uint32 DominatorGraph::DFS(Uint32 vx, Uint32 n)
|
||||
{
|
||||
semi[vx] = ++n;
|
||||
vertex[n] = label[vx] = vx;
|
||||
ancestor[vx] = child[vx] = 0;
|
||||
size[vx] = 1;
|
||||
|
||||
|
||||
ControlNode& node = *controlGraph.dfsList[VtoG[vx]];
|
||||
ControlEdge* successorEnd = node.getSuccessorsEnd();
|
||||
for (ControlEdge* successorPtr = node.getSuccessorsBegin(); successorPtr < successorEnd; successorPtr++) {
|
||||
Uint32 w = GtoV[successorPtr->getTarget().dfsNum];
|
||||
if (semi[w] == 0) {
|
||||
parent[w] = vx;
|
||||
n = DFS(w, n);
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void DominatorGraph::LINK(Uint32 vx, Uint32 w)
|
||||
{
|
||||
Uint32 s = w;
|
||||
|
||||
while (semi[label[w]] < semi[label[child[s]]]) {
|
||||
if (size[s] + size[child[child[s]]] >= (size[child[s]] << 1)) {
|
||||
ancestor[child[s]] = s;
|
||||
child[s] = child[child[s]];
|
||||
} else {
|
||||
size[child[s]] = size[s];
|
||||
s = ancestor[s] = child[s];
|
||||
}
|
||||
}
|
||||
label[s] = label[w];
|
||||
size[vx] += size[w];
|
||||
if(size[vx] < (size[w] << 1)) {
|
||||
Uint32 t = s;
|
||||
s = child[vx];
|
||||
child[vx] = t;
|
||||
}
|
||||
while( s != 0 ) {
|
||||
ancestor[s] = vx;
|
||||
s = child[s];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DominatorGraph::COMPRESS(Uint32 vx)
|
||||
{
|
||||
if(ancestor[ancestor[vx]] != 0) {
|
||||
COMPRESS(ancestor[vx]);
|
||||
if(semi[label[ancestor[vx]]] < semi[label[vx]])
|
||||
label[vx] = label[ancestor[vx]];
|
||||
ancestor[vx] = ancestor[ancestor[vx]];
|
||||
}
|
||||
}
|
||||
|
||||
Uint32 DominatorGraph::EVAL(Uint32 vx)
|
||||
{
|
||||
if(ancestor[vx] == 0)
|
||||
return label[vx];
|
||||
COMPRESS(vx);
|
||||
return (semi[label[ancestor[vx]]] >= semi[label[vx]]) ? label[vx] : label[ancestor[vx]];
|
||||
}
|
||||
|
||||
void DominatorGraph::build()
|
||||
{
|
||||
Uint32 n = DFS(GtoV[0], 0);
|
||||
size[0] = label[0] = semi[0];
|
||||
|
||||
for (Uint32 i = n; i >= 2; i--) {
|
||||
Uint32 w = vertex[i];
|
||||
|
||||
ControlNode& node = *controlGraph.dfsList[VtoG[w]];
|
||||
const DoublyLinkedList<ControlEdge>& predecessors = node.getPredecessors();
|
||||
for (DoublyLinkedList<ControlEdge>::iterator p = predecessors.begin(); !predecessors.done(p); p = predecessors.advance(p)) {
|
||||
Uint32 vx = GtoV[predecessors.get(p).getSource().dfsNum];
|
||||
Uint32 u = EVAL(vx);
|
||||
|
||||
if(semi[u] < semi[w])
|
||||
semi[w] = semi[u];
|
||||
}
|
||||
|
||||
DGLinkedList* elem = new DGLinkedList();
|
||||
elem->next = bucket[vertex[semi[w]]];
|
||||
elem->index = w;
|
||||
bucket[vertex[semi[w]]] = elem;
|
||||
|
||||
LINK(parent[w], w);
|
||||
|
||||
elem = bucket[parent[w]];
|
||||
while(elem != NULL) {
|
||||
Uint32 vx = elem->index;
|
||||
Uint32 u = EVAL(vx);
|
||||
dom[vx] = (semi[u] < semi[vx]) ? u : parent[w];
|
||||
elem = elem->next;
|
||||
}
|
||||
}
|
||||
|
||||
memset(size, '\0', n * sizeof(Uint32));
|
||||
Pool& pool = controlGraph.pool;
|
||||
nodes = new(pool) DGNode[n];
|
||||
|
||||
for(Uint32 j = 2; j <= n; j++) {
|
||||
Uint32 w = vertex[j];
|
||||
Uint32 d = dom[w];
|
||||
if(d != vertex[semi[w]]) {
|
||||
d = dom[d];
|
||||
dom[w] = d;
|
||||
}
|
||||
size[d]++;
|
||||
}
|
||||
dom[GtoV[0]] = 0;
|
||||
|
||||
for (Uint32 k = 1; k <= n; k++) {
|
||||
DGNode& node = nodes[VtoG[k]];
|
||||
Uint32 count = size[k];
|
||||
node.successorsEnd = node.successorsBegin = (count) ? new(pool) Uint32[count] : (Uint32*) 0;
|
||||
}
|
||||
|
||||
for (Uint32 l = 2; l <= n; l++)
|
||||
*(nodes[VtoG[dom[l]]].successorsEnd)++ = VtoG[l];
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
void DominatorGraph::printPretty(LogModuleObject log)
|
||||
{
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Dominator Graph:\n"));
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
for (Uint32 i = 0; i < nNodes; i++) {
|
||||
DGNode& node = nodes[i];
|
||||
if (node.successorsBegin != node.successorsEnd) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\tN%d dominates ", i));
|
||||
for (Uint32* successorsPtr = node.successorsBegin; successorsPtr < node.successorsEnd; successorsPtr++)
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("N%d ", *successorsPtr));
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
|
||||
|
||||
80
mozilla/ef/Compiler/RegisterAllocator/DominatorGraph.h
Normal file
80
mozilla/ef/Compiler/RegisterAllocator/DominatorGraph.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DOMINATOR_GRAPH_H_
|
||||
#define _DOMINATOR_GRAPH_H_
|
||||
|
||||
#include "LogModule.h"
|
||||
|
||||
class ControlGraph;
|
||||
|
||||
struct DGNode
|
||||
{
|
||||
Uint32* successorsBegin;
|
||||
Uint32* successorsEnd;
|
||||
};
|
||||
|
||||
struct DGLinkedList
|
||||
{
|
||||
DGLinkedList* next;
|
||||
Uint32 index;
|
||||
};
|
||||
|
||||
class DominatorGraph
|
||||
{
|
||||
private:
|
||||
|
||||
ControlGraph& controlGraph;
|
||||
|
||||
Uint32 vCount;
|
||||
|
||||
Uint32* VtoG;
|
||||
Uint32* GtoV;
|
||||
Uint32* parent;
|
||||
Uint32* semi;
|
||||
Uint32* vertex;
|
||||
Uint32* label;
|
||||
Uint32* size;
|
||||
Uint32* ancestor;
|
||||
Uint32* child;
|
||||
Uint32* dom;
|
||||
DGLinkedList** bucket;
|
||||
DGNode* nodes;
|
||||
|
||||
private:
|
||||
|
||||
void build();
|
||||
|
||||
Uint32 DFS(Uint32 vx, Uint32 n);
|
||||
void LINK(Uint32 vx, Uint32 w);
|
||||
void COMPRESS(Uint32 vx);
|
||||
Uint32 EVAL(Uint32 vx);
|
||||
|
||||
public:
|
||||
|
||||
DominatorGraph(ControlGraph& controlGraph);
|
||||
|
||||
Uint32* getSuccessorsBegin(Uint32 n) const {return nodes[n].successorsBegin;}
|
||||
Uint32* getSuccessorsEnd(Uint32 n) const {return nodes[n].successorsEnd;}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
#endif // _DOMINATOR_GRAPH_H_
|
||||
20
mozilla/ef/Compiler/RegisterAllocator/HashSet.cpp
Normal file
20
mozilla/ef/Compiler/RegisterAllocator/HashSet.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "HashSet.h"
|
||||
97
mozilla/ef/Compiler/RegisterAllocator/HashSet.h
Normal file
97
mozilla/ef/Compiler/RegisterAllocator/HashSet.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _HASH_SET_H_
|
||||
#define _HASH_SET_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include <string.h>
|
||||
|
||||
struct HashSetElement
|
||||
{
|
||||
Uint32 index;
|
||||
HashSetElement* next;
|
||||
};
|
||||
|
||||
class HashSet
|
||||
{
|
||||
private:
|
||||
|
||||
static const hashSize = 64;
|
||||
|
||||
// Return the hash code for the given element index.
|
||||
static Uint32 getHashCode(Uint32 index) {return index & (hashSize - 1);} // Could be better !
|
||||
|
||||
private:
|
||||
|
||||
Pool& allocationPool;
|
||||
HashSetElement** bucket;
|
||||
HashSetElement* free;
|
||||
|
||||
private:
|
||||
|
||||
// No copy constructor.
|
||||
HashSet(const HashSet&);
|
||||
// No copy operator.
|
||||
void operator = (const HashSet&);
|
||||
|
||||
public:
|
||||
|
||||
// Create a new HashSet.
|
||||
inline HashSet(Pool& pool, Uint32 universeSize);
|
||||
|
||||
// Clear the hashset.
|
||||
void clear();
|
||||
// Clear the element for the given index.
|
||||
void clear(Uint32 index);
|
||||
// Set the element for the given index.
|
||||
void set(Uint32 index);
|
||||
// Return true if the element at index is a member.
|
||||
bool test(Uint32 index) const;
|
||||
// Union with the given hashset.
|
||||
inline void or(const HashSet& set);
|
||||
// Intersection with the given hashset.
|
||||
inline void and(const HashSet& set);
|
||||
// Difference with the given hashset.
|
||||
inline void difference(const HashSet& set);
|
||||
|
||||
// Logical operators.
|
||||
HashSet& operator |= (const HashSet& set) {or(set); return *this;}
|
||||
HashSet& operator &= (const HashSet& set) {and(set); return *this;}
|
||||
HashSet& operator -= (const HashSet& set) {difference(set); return *this;}
|
||||
|
||||
// Iterator to conform with the set API.
|
||||
typedef HashSetElement* iterator;
|
||||
// Return the iterator for the first element of this set.
|
||||
iterator begin() const;
|
||||
// Return the next iterator.
|
||||
iterator advance(iterator pos) const;
|
||||
// Return true if the iterator is at the end of the set.
|
||||
bool done(iterator pos) const {return pos == NULL;}
|
||||
};
|
||||
|
||||
|
||||
inline HashSet::HashSet(Pool& pool, Uint32 /*universeSize*/)
|
||||
: allocationPool(pool), free(NULL)
|
||||
{
|
||||
bucket = new(pool) HashSetElement*[hashSize];
|
||||
memset(bucket, '\0', sizeof(HashSetElement*));
|
||||
}
|
||||
|
||||
#endif // _HASH_SET_H_
|
||||
213
mozilla/ef/Compiler/RegisterAllocator/IndexedPool.h
Normal file
213
mozilla/ef/Compiler/RegisterAllocator/IndexedPool.h
Normal file
@@ -0,0 +1,213 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _INDEXED_POOL_H_
|
||||
#define _INDEXED_POOL_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// IndexedPool<IndexedObjectSubclass> is an indexed pool of objects. The
|
||||
// template parameter 'IndexedObjectSubclass' must be a subclass of the struct
|
||||
// IndexedObject.
|
||||
//
|
||||
// When the indexed pool is ask to allocate and initialize a new object (using
|
||||
// the operator new(anIndexedPool) it will zero the memory used to store the
|
||||
// object and initialize the field 'index' of this object to its position in
|
||||
// the pool.
|
||||
//
|
||||
// An object allocated by the indexed pool can be freed by calling the method
|
||||
// IndexedPool::release(IndexedElement& objectIndex).
|
||||
//
|
||||
// example:
|
||||
//
|
||||
// IndexedPool<IndexedElement> elementPool;
|
||||
//
|
||||
// IndexedElement& element1 = *new(elementPool) IndexedElement();
|
||||
// IndexedElement& element2 = *new(elementPool) IndexedElement();
|
||||
//
|
||||
// indexedPool.release(element1);
|
||||
// IndexedElement& element3 = *new(elementPool) IndexedElement();
|
||||
//
|
||||
// At this point element1 is no longer a valid object, element2 is at
|
||||
// index 2 and element3 is at index 1.
|
||||
//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// IndexedObject -
|
||||
//
|
||||
|
||||
template<class Object>
|
||||
struct IndexedObject
|
||||
{
|
||||
Uint32 index; // Index in the pool.
|
||||
Object* next; // Used to link IndexedObject together.
|
||||
|
||||
Uint32 getIndex() {return index;}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// IndexedPool<IndexedObject> -
|
||||
//
|
||||
|
||||
template <class IndexedObject>
|
||||
class IndexedPool
|
||||
{
|
||||
private:
|
||||
|
||||
static const blockSize = 4; // Size of one block.
|
||||
|
||||
Uint32 nBlocks; // Number of blocks in the pool.
|
||||
IndexedObject** block; // Array of block pointers.
|
||||
IndexedObject* freeObjects; // Chained list of free IndexedObjects.
|
||||
Uint32 nextIndex; // Index of the next free object in the last block.
|
||||
|
||||
private:
|
||||
|
||||
void allocateAnotherBlock();
|
||||
IndexedObject& newObject();
|
||||
|
||||
public:
|
||||
|
||||
IndexedPool() : nBlocks(0), block(NULL), freeObjects(NULL), nextIndex(1) {}
|
||||
~IndexedPool();
|
||||
|
||||
IndexedObject& get(Uint32 index) const;
|
||||
void release(IndexedObject& object);
|
||||
|
||||
void setSize(Uint32 size) {assert(size < nextIndex); nextIndex = size;}
|
||||
|
||||
// Return the universe size.
|
||||
Uint32 getSize() {return nextIndex;}
|
||||
|
||||
friend void* operator new(size_t, IndexedPool<IndexedObject>& pool); // Needs to call newObject().
|
||||
};
|
||||
|
||||
// Free all the memory allocated for this object.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
IndexedPool<IndexedObject>::~IndexedPool()
|
||||
{
|
||||
for (Uint32 n = 0; n < nBlocks; n++)
|
||||
free(&((IndexedObject **) &block[n][n*blockSize])[-(n + 1)]);
|
||||
}
|
||||
|
||||
// Release the given. This object will be iserted in the chained
|
||||
// list of free IndexedObjects. To minimize the fragmentation the chained list
|
||||
// is ordered by ascending indexes.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
void IndexedPool<IndexedObject>::release(IndexedObject& object)
|
||||
{
|
||||
Uint32 index = object.index;
|
||||
IndexedObject* list = freeObjects;
|
||||
|
||||
assert(&object == &get(index)); // Make sure that object is owned by this pool.
|
||||
|
||||
if (list == NULL) { // The list is empty.
|
||||
freeObjects = &object;
|
||||
object.next = NULL;
|
||||
} else { // The list contains at least 1 element.
|
||||
if (index < list->index) { // insert as first element.
|
||||
freeObjects = &object;
|
||||
object.next = list;
|
||||
} else { // Find this object's place.
|
||||
while ((list->next) != NULL && (list->next->index < index))
|
||||
list = list->next;
|
||||
|
||||
object.next = list->next;
|
||||
list->next = &object;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// Sanity check to be sure that the list is correctly ordered.
|
||||
for (IndexedObject* obj = freeObjects; obj != NULL; obj = obj->next)
|
||||
if (obj->next != NULL)
|
||||
assert(obj->index < obj->next->index);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Create a new block of IndexedObjects. We will allocate the memory to
|
||||
// store IndexedPool::blockSize IndexedObject and the new Array of block
|
||||
// pointers.
|
||||
// The newly created IndexedObjects will not be initialized.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
void IndexedPool<IndexedObject>::allocateAnotherBlock()
|
||||
{
|
||||
void* memory = (void *) malloc((nBlocks + 1) * sizeof(Uint32) + blockSize * sizeof(IndexedObject));
|
||||
|
||||
memcpy(memory, block, nBlocks * sizeof(Uint32));
|
||||
|
||||
block = (IndexedObject **) memory;
|
||||
IndexedObject* objects = (IndexedObject *) &block[nBlocks + 1];
|
||||
|
||||
block[nBlocks] = &objects[-(nBlocks * blockSize)];
|
||||
nBlocks++;
|
||||
}
|
||||
|
||||
// Return the IndexedObject at the position 'index' in the pool.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
IndexedObject& IndexedPool<IndexedObject>::get(Uint32 index) const
|
||||
{
|
||||
Uint32 blockIndex = index / blockSize;
|
||||
assert(blockIndex < nBlocks);
|
||||
|
||||
return block[blockIndex][index];
|
||||
}
|
||||
|
||||
// Return the reference of an unused object in the pool.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
IndexedObject& IndexedPool<IndexedObject>::newObject()
|
||||
{
|
||||
if (freeObjects != NULL) {
|
||||
IndexedObject& newObject = *freeObjects;
|
||||
freeObjects = newObject.next;
|
||||
return newObject;
|
||||
}
|
||||
|
||||
Uint32 nextIndex = this->nextIndex++;
|
||||
Uint32 blockIndex = nextIndex / blockSize;
|
||||
|
||||
while (blockIndex >= nBlocks)
|
||||
allocateAnotherBlock();
|
||||
|
||||
IndexedObject& newObject = block[blockIndex][nextIndex];
|
||||
newObject.index = nextIndex;
|
||||
|
||||
return newObject;
|
||||
}
|
||||
|
||||
// Return the address of the next unsused object in the given
|
||||
// indexed pool. The field index of the newly allocated object
|
||||
// will be initialized to the corresponding index of this object
|
||||
// in the pool.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
void* operator new(size_t size, IndexedPool<IndexedObject>& pool)
|
||||
{
|
||||
assert(size == sizeof(IndexedObject));
|
||||
return (void *) &pool.newObject();
|
||||
}
|
||||
|
||||
#endif // _INDEXED_POOL_H_
|
||||
258
mozilla/ef/Compiler/RegisterAllocator/InterferenceGraph.h
Normal file
258
mozilla/ef/Compiler/RegisterAllocator/InterferenceGraph.h
Normal file
@@ -0,0 +1,258 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _INTERFERENCE_GRAPH_H_
|
||||
#define _INTERFERENCE_GRAPH_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "Primitives.h"
|
||||
#include "Instruction.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "RegisterPressure.h"
|
||||
#include "SparseSet.h"
|
||||
#include <string.h>
|
||||
|
||||
struct InterferenceVector
|
||||
{
|
||||
Uint32 count;
|
||||
InterferenceVector* next;
|
||||
RegisterName* neighbors;
|
||||
|
||||
InterferenceVector() : count(0), next(NULL) {}
|
||||
};
|
||||
|
||||
class RegisterAllocator;
|
||||
|
||||
template <class RegisterPressure>
|
||||
class InterferenceGraph
|
||||
{
|
||||
private:
|
||||
|
||||
RegisterAllocator& registerAllocator;
|
||||
|
||||
RegisterPressure::Set* interferences;
|
||||
InterferenceVector** vector;
|
||||
Uint32* offset;
|
||||
Uint32 rangeCount;
|
||||
|
||||
private:
|
||||
|
||||
// No copy constructor.
|
||||
InterferenceGraph(const InterferenceGraph&);
|
||||
// No copy operator.
|
||||
void operator = (const InterferenceGraph&);
|
||||
|
||||
// Check if reg is a member of the universe.
|
||||
void checkMember(RegisterName name) {assert(name < rangeCount);}
|
||||
// Return the edge index for the interference between name1 and name2.
|
||||
Uint32 getEdgeIndex(RegisterName name1, RegisterName name2);
|
||||
|
||||
public:
|
||||
InterferenceGraph(RegisterAllocator& registerAllocator) : registerAllocator(registerAllocator) {}
|
||||
|
||||
// Calculate the interferences.
|
||||
void build();
|
||||
// Return true if reg1 and reg2 interfere.
|
||||
bool interfere(RegisterName name1, RegisterName name2);
|
||||
// Return the interference vector for the given register or NULL if there is none.
|
||||
InterferenceVector* getInterferenceVector(RegisterName name) {return vector[name];}
|
||||
// Set the interference between name1 and name2.
|
||||
void setInterference(RegisterName name1, RegisterName name2);
|
||||
// Set the interference vector for the given register.
|
||||
void setInterferenceVector(RegisterName name, InterferenceVector* v) {vector[name] = v;}
|
||||
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
// Print the interferences.
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void InterferenceGraph<RegisterPressure>::build()
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
this->rangeCount = rangeCount;
|
||||
|
||||
// Initialize the structures.
|
||||
//
|
||||
offset = new(pool) Uint32[rangeCount + 1];
|
||||
vector = new(pool) InterferenceVector*[rangeCount];
|
||||
memset(vector, '\0', sizeof(InterferenceVector*) * rangeCount);
|
||||
|
||||
Uint32 o = 0;
|
||||
offset[0] = 0;
|
||||
for (Uint32 i = 1; i <= rangeCount; ++i) {
|
||||
offset[i] = o;
|
||||
o += i;
|
||||
}
|
||||
|
||||
interferences = new(pool) RegisterPressure::Set(pool, (rangeCount * rangeCount) / 2);
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
LivenessInfo<RegisterPressure> liveness = Liveness<RegisterPressure>::analysis(controlGraph, rangeCount, name2range);
|
||||
registerAllocator.liveness = liveness;
|
||||
SparseSet currentLive(pool, rangeCount);
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
currentLive = liveness.liveOut[n];
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
// Handle the copy instruction to avoid unnecessary interference between the 2 registers.
|
||||
if ((instruction.getFlags() & ifCopy) != 0) {
|
||||
assert(useBegin != useEnd && useBegin[0].isRegister());
|
||||
currentLive.clear(name2range[useBegin[0].getRegisterName()]);
|
||||
}
|
||||
|
||||
// Create the interferences.
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName define = name2range[definePtr->getRegisterName()];
|
||||
|
||||
for (SparseSet::iterator e = currentLive.begin(); !currentLive.done(e); e = currentLive.advance(e)) {
|
||||
RegisterName live = RegisterName(currentLive.get(e));
|
||||
|
||||
if ((live != define) && !interfere(live, define) && registerAllocator.canInterfere(live, define)) {
|
||||
|
||||
if (vector[define] == NULL)
|
||||
vector[define] = new(pool) InterferenceVector();
|
||||
vector[define]->count++;
|
||||
|
||||
if (vector[live] == NULL)
|
||||
vector[live] = new(pool) InterferenceVector();
|
||||
vector[live]->count++;
|
||||
|
||||
setInterference(live, define);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now update the liveness.
|
||||
//
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentLive.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
currentLive.set(name2range[usePtr->getRegisterName()]);
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate the memory to store the interferences.
|
||||
//
|
||||
for (Uint32 e = 0; e < rangeCount; e++)
|
||||
if (vector[e] != NULL) {
|
||||
InterferenceVector& v = *vector[e];
|
||||
v.neighbors = new(pool) RegisterName[v.count];
|
||||
v.count = 0;
|
||||
}
|
||||
|
||||
// Initialize the edges.
|
||||
//
|
||||
if (RegisterPressure::Set::isOrdered()) {
|
||||
RegisterName name1 = RegisterName(0);
|
||||
|
||||
for (RegisterPressure::Set::iterator i = interferences->begin(); !interferences->done(i); i = interferences->advance(i)) {
|
||||
Uint32 interferenceIndex = interferences->get(i);
|
||||
|
||||
while(interferenceIndex >= offset[name1 + 1])
|
||||
name1 = RegisterName(name1 + 1);
|
||||
|
||||
assert((interferenceIndex >= offset[name1]) && (interferenceIndex < offset[name1 + 1]));
|
||||
|
||||
RegisterName name2 = RegisterName(interferenceIndex - offset[name1]);
|
||||
|
||||
assert(interfere(name1, name2));
|
||||
|
||||
InterferenceVector& vector1 = *vector[name1];
|
||||
vector1.neighbors[vector1.count++] = name2;
|
||||
|
||||
InterferenceVector& vector2 = *vector[name2];
|
||||
vector2.neighbors[vector2.count++] = name1;
|
||||
}
|
||||
} else {
|
||||
trespass("not Implemented"); // FIX: need one more pass to initialize the vectors.
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
Uint32 InterferenceGraph<RegisterPressure>::getEdgeIndex(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
checkMember(name1); checkMember(name2);
|
||||
assert(name1 != name2); // This is not possible.
|
||||
return (name1 < name2) ? offset[name2] + name1 : offset[name1] + name2;
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void InterferenceGraph<RegisterPressure>::setInterference(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
interferences->set(getEdgeIndex(name1, name2));
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool InterferenceGraph<RegisterPressure>::interfere(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
return interferences->test(getEdgeIndex(name1, name2));
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
template <class RegisterPressure>
|
||||
void InterferenceGraph<RegisterPressure>::printPretty(LogModuleObject log)
|
||||
{
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Interference Vectors:\n"));
|
||||
for (Uint32 i = 1; i < rangeCount; i++) {
|
||||
if (vector[i] != NULL) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\tvr%d: (", i));
|
||||
for (InterferenceVector* v = vector[i]; v != NULL; v = v->next)
|
||||
for (Uint32 j = 0; j < v->count; j++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%d", v->neighbors[j]));
|
||||
if (v->next != NULL || j != (v->count - 1))
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (","));
|
||||
}
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (")\n"));
|
||||
}
|
||||
}
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Interference Matrix:\n"));
|
||||
for (RegisterName name1 = RegisterName(1); name1 < rangeCount; name1 = RegisterName(name1 + 1)) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\t%d:\t", name1));
|
||||
for (RegisterName name2 = RegisterName(1); name2 < rangeCount; name2 = RegisterName(name2 + 1))
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%c", ((name1 != name2) && interfere(name1, name2)) ? '1' : '0'));
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
#endif // _INTERFERENCE_GRAPH_H_
|
||||
87
mozilla/ef/Compiler/RegisterAllocator/LiveRange.h
Normal file
87
mozilla/ef/Compiler/RegisterAllocator/LiveRange.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _LIVE_RANGE_H_
|
||||
#define _LIVE_RANGE_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Primitives.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct LiveRange
|
||||
{
|
||||
static void build(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void LiveRange<RegisterPressure>::build(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
// Intialize the lookup table.
|
||||
//
|
||||
Uint32 nameCount = registerAllocator.nameCount;
|
||||
RegisterName* nameTable = new(registerAllocator.pool) RegisterName[2*nameCount];
|
||||
RegisterName* rangeName = &nameTable[nameCount];
|
||||
|
||||
init(rangeName, nameCount);
|
||||
|
||||
// Walk the graph.
|
||||
//
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
SparseSet destination(registerAllocator.pool, nameCount);
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
|
||||
destination.clear();
|
||||
for (InstructionList::iterator i = phiNodes.begin(); !phiNodes.done(i); i = phiNodes.advance(i)) {
|
||||
Instruction& phiNode = phiNodes.get(i);
|
||||
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd() && phiNode.getInstructionDefineBegin()[0].isRegister());
|
||||
destination.set(findRoot(phiNode.getInstructionDefineBegin()[0].getRegisterName(), rangeName));
|
||||
}
|
||||
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& phiNode = phiNodes.get(p);
|
||||
|
||||
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd() && phiNode.getInstructionDefineBegin()[0].isRegister());
|
||||
RegisterName destinationName = phiNode.getInstructionDefineBegin()[0].getRegisterName();
|
||||
RegisterName destinationRoot = findRoot(destinationName, rangeName);
|
||||
|
||||
InstructionUse* useEnd = phiNode.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = phiNode.getInstructionUseBegin(); usePtr < useEnd; usePtr++) {
|
||||
assert(usePtr->isRegister());
|
||||
RegisterName sourceName = usePtr->getRegisterName();
|
||||
RegisterName sourceRoot = findRoot(sourceName, rangeName);
|
||||
|
||||
if (sourceRoot != destinationRoot && !destination.test(sourceRoot))
|
||||
rangeName[sourceRoot] = destinationRoot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerAllocator.rangeCount = compress(registerAllocator.name2range, rangeName, nameCount, nameCount);
|
||||
}
|
||||
|
||||
#endif // _LIVE_RANGE_H_
|
||||
163
mozilla/ef/Compiler/RegisterAllocator/LiveRangeGraph.h
Normal file
163
mozilla/ef/Compiler/RegisterAllocator/LiveRangeGraph.h
Normal file
@@ -0,0 +1,163 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _LIVE_RANGE_GRAPH_
|
||||
#define _LIVE_RANGE_GRAPH_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterTypes.h"
|
||||
|
||||
class RegisterAllocator;
|
||||
|
||||
template <class RegisterPressure>
|
||||
class LiveRangeGraph
|
||||
{
|
||||
private:
|
||||
|
||||
RegisterAllocator& registerAllocator;
|
||||
|
||||
RegisterPressure::Set* edges;
|
||||
Uint32 rangeCount;
|
||||
|
||||
public:
|
||||
//
|
||||
//
|
||||
LiveRangeGraph(RegisterAllocator& registerAllocator) : registerAllocator(registerAllocator) {}
|
||||
|
||||
//
|
||||
//
|
||||
void build();
|
||||
|
||||
//
|
||||
//
|
||||
void addEdge(RegisterName name1, RegisterName name2);
|
||||
|
||||
//
|
||||
//
|
||||
bool haveEdge(RegisterName name1, RegisterName name2);
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
//
|
||||
//
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void LiveRangeGraph<RegisterPressure>::build()
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
this->rangeCount = rangeCount;
|
||||
|
||||
edges = new(pool) RegisterPressure::Set(pool, rangeCount * rangeCount);
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
LivenessInfo<RegisterPressure>& liveness = registerAllocator.liveness;
|
||||
SparseSet currentLive(pool, rangeCount);
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
currentLive = liveness.liveOut[n];
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
if ((instruction.getFlags() & ifCopy) != 0) {
|
||||
assert(useBegin != useEnd && useBegin[0].isRegister());
|
||||
currentLive.clear(name2range[useBegin[0].getRegisterName()]);
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName define = name2range[definePtr->getRegisterName()];
|
||||
|
||||
for (SparseSet::iterator l = currentLive.begin(); !currentLive.done(l); l = currentLive.advance(l)) {
|
||||
RegisterName live = RegisterName(currentLive.get(l));
|
||||
if (define != live && registerAllocator.canInterfere(define, live))
|
||||
addEdge(define, live);
|
||||
}
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentLive.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
currentLive.set(name2range[usePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName use = name2range[usePtr->getRegisterName()];
|
||||
|
||||
for (SparseSet::iterator l = currentLive.begin(); !currentLive.done(l); l = currentLive.advance(l)) {
|
||||
RegisterName live = RegisterName(currentLive.get(l));
|
||||
if (use != live && registerAllocator.canInterfere(use, live))
|
||||
addEdge(use, live);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void LiveRangeGraph<RegisterPressure>::addEdge(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
assert(name1 != name2);
|
||||
edges->set(name1 * rangeCount + name2);
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool LiveRangeGraph<RegisterPressure>::haveEdge(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
assert(name1 != name2);
|
||||
return edges->test(name1 * rangeCount + name2);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
template <class RegisterPressure>
|
||||
void LiveRangeGraph<RegisterPressure>::printPretty(LogModuleObject log)
|
||||
{
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Live ranges graph:\n"));
|
||||
for (RegisterName name1 = RegisterName(1); name1 < rangeCount; name1 = RegisterName(name1 + 1)) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\t%d:\t", name1));
|
||||
for (RegisterName name2 = RegisterName(1); name2 < rangeCount; name2 = RegisterName(name2 + 1))
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%c", ((name1 != name2) && haveEdge(name1, name2)) ? '1' : '0'));
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
#endif // _LIVE_RANGE_GRAPH_
|
||||
21
mozilla/ef/Compiler/RegisterAllocator/Liveness.cpp
Normal file
21
mozilla/ef/Compiler/RegisterAllocator/Liveness.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Liveness.h"
|
||||
|
||||
301
mozilla/ef/Compiler/RegisterAllocator/Liveness.h
Normal file
301
mozilla/ef/Compiler/RegisterAllocator/Liveness.h
Normal file
@@ -0,0 +1,301 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _LIVENESS_H_
|
||||
#define _LIVENESS_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterTypes.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// LivenessInfo -
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct LivenessInfo
|
||||
{
|
||||
RegisterPressure::Set* liveIn;
|
||||
RegisterPressure::Set* liveOut;
|
||||
DEBUG_LOG_ONLY(Uint32 size);
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Liveness
|
||||
//
|
||||
// The liveness is defined by the following data-flow equations:
|
||||
//
|
||||
// LiveIn(n) = LocalLive(n) U (LiveOut(n) - Killed(n)).
|
||||
// LiveOut(n) = U LiveIn(s) (s a successor of n).
|
||||
//
|
||||
// where LocalLive(n) is the set of used registers in the block n, Killed(n)
|
||||
// is the set of defined registers in the block n, LiveIn(n) is the set of
|
||||
// live registers at the begining of the block n and LiveOut(n) is the set
|
||||
// of live registers at the end of the block n.
|
||||
//
|
||||
//
|
||||
// We will compute the liveness analysis in two stages:
|
||||
//
|
||||
// 1- Build LocalLive(n) (wich is an approximation of LiveIn(n)) and Killed(n)
|
||||
// for each block n.
|
||||
// 2- Perform a backward data-flow analysis to propagate the liveness information
|
||||
// through the entire control-flow graph.
|
||||
//
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct Liveness
|
||||
{
|
||||
static LivenessInfo<RegisterPressure> analysis(ControlGraph& controlGraph, Uint32 rangeCount, const RegisterName* name2range);
|
||||
static LivenessInfo<RegisterPressure> analysis(ControlGraph& controlGraph, Uint32 nameCount);
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
LivenessInfo<RegisterPressure> Liveness<RegisterPressure>::analysis(ControlGraph& controlGraph, Uint32 rangeCount, const RegisterName* name2range)
|
||||
{
|
||||
Pool& pool = controlGraph.pool;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
// Allocate the temporary sets.
|
||||
RegisterPressure::Set* killed = new(pool) RegisterPressure::Set[nNodes](pool, rangeCount);
|
||||
|
||||
// Allocate the globals sets.
|
||||
RegisterPressure::Set* liveIn = new(pool) RegisterPressure::Set[nNodes](pool, rangeCount);
|
||||
RegisterPressure::Set* liveOut = new(pool) RegisterPressure::Set[nNodes](pool, rangeCount);
|
||||
|
||||
// First stage of the liveness analysis: Compute the sets LocalLive(stored in LiveIn) and Killed.
|
||||
//
|
||||
for (Uint32 n = 0; n < (nNodes - 1); n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
RegisterPressure::Set& currentLocalLive = liveIn[n];
|
||||
RegisterPressure::Set& currentKilled = killed[n];
|
||||
|
||||
// Find the instructions contributions to the sets LocalLive and Killed.
|
||||
//
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
// If a VirtualRegister is 'used' before being 'defined' then we add it to set LocalLive.
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
Uint32 index = name2range[usePtr->getRegisterName()];
|
||||
|
||||
if (!currentKilled.test(index))
|
||||
currentLocalLive.set(index);
|
||||
}
|
||||
|
||||
// If a Virtualregister is 'defined' then we add it to the set Killed.
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentKilled.set(name2range[definePtr->getRegisterName()]);
|
||||
}
|
||||
}
|
||||
|
||||
// Second stage of the liveness analysis: We propagate the LiveIn & LiveOut through the entire
|
||||
// control-flow graph.
|
||||
//
|
||||
RegisterPressure::Set temp(pool, rangeCount);
|
||||
|
||||
bool changed;
|
||||
do {
|
||||
changed = false;
|
||||
|
||||
// For all nodes is this graph except the endNode.
|
||||
for (Int32 n = (nNodes - 2); n >= 0; n--) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
RegisterPressure::Set& currentLiveIn = liveIn[n];
|
||||
RegisterPressure::Set& currentLiveOut = liveOut[n];
|
||||
|
||||
// Compute temp = Union of LiveIn(s) (s a successor of this node) | usedByPhiNodes(n).
|
||||
// temp will be the new LiveOut(n).
|
||||
Uint32 nSuccessors = node.nSuccessors();
|
||||
if (nSuccessors != 0) {
|
||||
temp = liveIn[node.nthSuccessor(0).getTarget().dfsNum];
|
||||
for (Uint32 s = 1; s < nSuccessors; s++)
|
||||
temp |= liveIn[node.nthSuccessor(s).getTarget().dfsNum];
|
||||
} else
|
||||
temp.clear();
|
||||
|
||||
// If temp and LiveOut(n) differ then set LiveOut(n) = temp and recalculate the
|
||||
// new LiveIn(n).
|
||||
if (currentLiveOut != temp) {
|
||||
currentLiveOut = temp;
|
||||
temp -= killed[n]; // FIX: could be optimized with one call to unionDiff !
|
||||
temp |= currentLiveIn;
|
||||
|
||||
if (currentLiveIn != temp) {
|
||||
currentLiveIn = temp;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(changed);
|
||||
|
||||
LivenessInfo<RegisterPressure> liveness;
|
||||
liveness.liveIn = liveIn;
|
||||
liveness.liveOut = liveOut;
|
||||
DEBUG_LOG_ONLY(liveness.size = nNodes);
|
||||
return liveness;
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
LivenessInfo<RegisterPressure> Liveness<RegisterPressure>::analysis(ControlGraph& controlGraph, Uint32 nameCount)
|
||||
{
|
||||
Pool& pool = controlGraph.pool;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
// Allocate the temporary sets.
|
||||
RegisterPressure::Set* killed = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
|
||||
RegisterPressure::Set* usedByPhiNodes = NULL;
|
||||
|
||||
// Allocate the globals sets.
|
||||
RegisterPressure::Set* liveIn = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
|
||||
RegisterPressure::Set* liveOut = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
|
||||
|
||||
// First stage of the liveness analysis: Compute the sets LocalLive(stored in LiveIn) and Killed.
|
||||
//
|
||||
for (Uint32 n = 0; n < (nNodes - 1); n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
RegisterPressure::Set& currentLocalLive = liveIn[n];
|
||||
RegisterPressure::Set& currentKilled = killed[n];
|
||||
|
||||
InstructionList& phiNodes = node.getPhiNodeInstructions();
|
||||
|
||||
if ((usedByPhiNodes == NULL) && !phiNodes.empty())
|
||||
usedByPhiNodes = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
|
||||
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& phiNode = phiNodes.get(p);
|
||||
|
||||
InstructionDefine& define = phiNode.getInstructionDefineBegin()[0];
|
||||
currentKilled.set(define.getRegisterName());
|
||||
|
||||
typedef DoublyLinkedList<ControlEdge> ControlEdgeList;
|
||||
const ControlEdgeList& predecessors = node.getPredecessors();
|
||||
ControlEdgeList::iterator p = predecessors.begin();
|
||||
InstructionUse* useEnd = phiNode.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = phiNode.getInstructionUseBegin(); usePtr < useEnd; usePtr++, p = predecessors.advance(p))
|
||||
if (usePtr->isRegister())
|
||||
usedByPhiNodes[predecessors.get(p).getSource().dfsNum].set(usePtr->getRegisterName());
|
||||
}
|
||||
|
||||
// Find the instructions contributions to the sets LocalLive and Killed.
|
||||
//
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
// If a VirtualRegister is 'used' before being 'defined' then we add it to set LocalLive.
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
Uint32 index = usePtr->getRegisterName();
|
||||
|
||||
if (!currentKilled.test(index))
|
||||
currentLocalLive.set(index);
|
||||
}
|
||||
|
||||
// If a Virtualregister is 'defined' then we add it to the set Killed.
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentKilled.set(definePtr->getRegisterName());
|
||||
}
|
||||
}
|
||||
|
||||
// Second stage of the liveness analysis: We propagate the LiveIn & LiveOut through the entire
|
||||
// control-flow graph.
|
||||
//
|
||||
RegisterPressure::Set temp(pool, nameCount);
|
||||
|
||||
bool changed;
|
||||
do {
|
||||
changed = false;
|
||||
|
||||
// For all nodes is this graph except the endNode.
|
||||
for (Int32 n = (nNodes - 2); n >= 0; n--) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
RegisterPressure::Set& currentLiveIn = liveIn[n];
|
||||
RegisterPressure::Set& currentLiveOut = liveOut[n];
|
||||
|
||||
// Compute temp = Union of LiveIn(s) (s a successor of this node) | usedByPhiNodes(n).
|
||||
// temp will be the new LiveOut(n).
|
||||
Uint32 nSuccessors = node.nSuccessors();
|
||||
if (nSuccessors != 0) {
|
||||
temp = liveIn[node.nthSuccessor(0).getTarget().dfsNum];
|
||||
for (Uint32 s = 1; s < nSuccessors; s++)
|
||||
temp |= liveIn[node.nthSuccessor(s).getTarget().dfsNum];
|
||||
} else
|
||||
temp.clear();
|
||||
|
||||
// Insert the phiNodes contribution.
|
||||
if (usedByPhiNodes != NULL)
|
||||
temp |= usedByPhiNodes[n];
|
||||
|
||||
// If temp and LiveOut(n) differ then set LiveOut(n) = temp and recalculate the
|
||||
// new LiveIn(n).
|
||||
if (currentLiveOut != temp) {
|
||||
currentLiveOut = temp;
|
||||
temp -= killed[n]; // FIX: could be optimized with one call to unionDiff !
|
||||
temp |= currentLiveIn;
|
||||
|
||||
if (currentLiveIn != temp) {
|
||||
currentLiveIn = temp;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(changed);
|
||||
|
||||
LivenessInfo<RegisterPressure> liveness;
|
||||
liveness.liveIn = liveIn;
|
||||
liveness.liveOut = liveOut;
|
||||
DEBUG_LOG_ONLY(liveness.size = nNodes);
|
||||
return liveness;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
template <class RegisterPressure>
|
||||
void LivenessInfo<RegisterPressure>::printPretty(LogModuleObject log)
|
||||
{
|
||||
for (Uint32 n = 0; n < size; n++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Node N%d:\n\tliveIn = ", n));
|
||||
liveIn[n].printPretty(log);
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\tliveOut = "));
|
||||
liveOut[n].printPretty(log);
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
#endif // _LIVENESS_H_
|
||||
40
mozilla/ef/Compiler/RegisterAllocator/Makefile
Normal file
40
mozilla/ef/Compiler/RegisterAllocator/Makefile
Normal file
@@ -0,0 +1,40 @@
|
||||
#! gmake
|
||||
|
||||
DEPTH = ../..
|
||||
|
||||
MODULE_NAME = RegisterAllocator
|
||||
|
||||
include $(DEPTH)/config/config.mk
|
||||
|
||||
INCLUDES += \
|
||||
-I$(DEPTH)/Utilities/General \
|
||||
-I$(DEPTH)/Utilities/zlib \
|
||||
-I$(DEPTH)/Runtime/ClassReader \
|
||||
-I$(DEPTH)/Runtime/NativeMethods \
|
||||
-I$(DEPTH)/Runtime/System \
|
||||
-I$(DEPTH)/Runtime/ClassInfo \
|
||||
-I$(DEPTH)/Runtime/FileReader \
|
||||
-I$(DEPTH)/Compiler/PrimitiveGraph \
|
||||
-I$(DEPTH)/Compiler/FrontEnd \
|
||||
-I$(DEPTH)/Compiler/Optimizer \
|
||||
-I$(DEPTH)/Compiler/CodeGenerator \
|
||||
-I$(DEPTH)/Compiler/CodeGenerator/md \
|
||||
-I$(DEPTH)/Compiler/CodeGenerator/md/$(CPU_ARCH) \
|
||||
-I$(DEPTH)/Compiler/RegisterAllocator \
|
||||
-I$(DEPTH)/Driver/StandAloneJava \
|
||||
-I$(DEPTH)/Debugger \
|
||||
$(NULL)
|
||||
|
||||
CXXSRCS = \
|
||||
RegisterAllocator.cpp \
|
||||
RegisterAllocatorTools.cpp \
|
||||
DominatorGraph.cpp \
|
||||
VirtualRegister.cpp \
|
||||
BitSet.cpp \
|
||||
SparseSet.cpp \
|
||||
$(NULL)
|
||||
|
||||
|
||||
include $(DEPTH)/config/rules.mk
|
||||
|
||||
libs:: $(MODULE)
|
||||
392
mozilla/ef/Compiler/RegisterAllocator/PhiNodeRemover.h
Normal file
392
mozilla/ef/Compiler/RegisterAllocator/PhiNodeRemover.h
Normal file
@@ -0,0 +1,392 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _PHI_NODE_REMOVER_H_
|
||||
#define _PHI_NODE_REMOVER_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "DominatorGraph.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "RegisterPressure.h"
|
||||
#include "Liveness.h"
|
||||
#include "Instruction.h"
|
||||
#include "InstructionEmitter.h"
|
||||
#include "SparseSet.h"
|
||||
#include <string.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterNameNode -
|
||||
|
||||
struct RegisterNameNode
|
||||
{
|
||||
RegisterNameNode* next;
|
||||
RegisterName newName;
|
||||
Uint32 nextPushed;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// CopyData -
|
||||
|
||||
struct CopyData
|
||||
{
|
||||
RegisterName source;
|
||||
RegisterClassKind classKind;
|
||||
Uint32 useCount;
|
||||
bool isLiveOut;
|
||||
RegisterName sourceNameToUse;
|
||||
RegisterName temporaryName;
|
||||
RegisterNameNode* newName;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// PhiNodeRemover<RegisterPressure> -
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct PhiNodeRemover
|
||||
{
|
||||
// Replace the phi nodes by copy instructions.
|
||||
static void replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter);
|
||||
};
|
||||
|
||||
// Split some of the critical edges and return true if there are still some
|
||||
// in the graph after that.
|
||||
//
|
||||
static bool splitCriticalEdges(ControlGraph& /*cg*/)
|
||||
{
|
||||
// FIX: not implemented.
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void pushName(Pool& pool, RegisterNameNode** stack, SparseSet& pushed, Uint32* nodeListPointer, RegisterName oldName, RegisterName newName)
|
||||
{
|
||||
RegisterNameNode& newNode = *new(pool) RegisterNameNode();
|
||||
|
||||
if (pushed.test(oldName))
|
||||
(*stack)->newName = newName;
|
||||
else {
|
||||
newNode.newName = newName;
|
||||
newNode.nextPushed = *nodeListPointer;
|
||||
*nodeListPointer = oldName;
|
||||
newNode.next = *stack;
|
||||
*stack = &newNode;
|
||||
pushed.set(oldName);
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void PhiNodeRemover<RegisterPressure>::replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter)
|
||||
{
|
||||
Pool& pool = controlGraph.pool;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
// Initialize the local variables.
|
||||
//
|
||||
|
||||
// When we insert the copies we will also need to create new VirtualRegisters for
|
||||
// the insertion of temporaries. The maximum number of temporary register will not
|
||||
// exceed the number of phiNodes in the primitive graph.
|
||||
Uint32 nameCount = vrManager.getSize();
|
||||
Uint32 maxNameCount = nameCount;
|
||||
for (Uint32 n = 0; n < nNodes; n++)
|
||||
maxNameCount += nodes[n]->getPhiNodes().length();
|
||||
|
||||
// If the CFG contains some critical edges (backward edge which source has more than one
|
||||
// outgoing edge and destination has more than one incomimg edge) then we need the liveness
|
||||
// information to be able to insert temporary copies.
|
||||
RegisterPressure::Set* liveOut = NULL;
|
||||
if (splitCriticalEdges(controlGraph))
|
||||
liveOut = Liveness<LowRegisterPressure>::analysis(controlGraph, nameCount).liveOut;
|
||||
|
||||
DominatorGraph dGraph(controlGraph);
|
||||
|
||||
SparseSet pushed(pool, maxNameCount);
|
||||
SparseSet destinationList(pool, maxNameCount);
|
||||
SparseSet workList(pool, maxNameCount);
|
||||
|
||||
CopyData* copyStats = new(pool) CopyData[maxNameCount];
|
||||
memset(copyStats, '\0', maxNameCount*sizeof(CopyData));
|
||||
|
||||
struct NodeStack {
|
||||
Uint32* next;
|
||||
Uint32* limit;
|
||||
Uint32 pushedList;
|
||||
};
|
||||
|
||||
// Allocate the node stack and initialize the node stack pointer.
|
||||
NodeStack* nodeStack = new(pool) NodeStack[nNodes + 1];
|
||||
NodeStack* nodeStackPtr = nodeStack;
|
||||
|
||||
// We start by the begin node.
|
||||
Uint32 startNode = 0;
|
||||
Uint32* next = &startNode;
|
||||
Uint32* limit = &startNode + 1;
|
||||
|
||||
while (true) {
|
||||
|
||||
if (next == limit) {
|
||||
// If there are no more node in the sibling, we have to pop the current
|
||||
// frame from the stack and update the copyStats of the pushed nodes.
|
||||
//
|
||||
if (nodeStackPtr == nodeStack)
|
||||
// We are at the bottom of the stack and there are no more nodes
|
||||
// to look at. We are done !
|
||||
break;
|
||||
|
||||
--nodeStackPtr;
|
||||
// We are done with all the children of this node in the dominator tree.
|
||||
// We need to update the copy information of all the new names pushed
|
||||
// during the walk over this node.
|
||||
Uint32 pushedList = nodeStackPtr->pushedList;
|
||||
while (pushedList != 0) {
|
||||
Uint32 nextName = copyStats[pushedList].newName->nextPushed;
|
||||
copyStats[pushedList].newName = copyStats[pushedList].newName->next;
|
||||
pushedList = nextName;
|
||||
}
|
||||
|
||||
// restore the previous frame.
|
||||
next = nodeStackPtr->next;
|
||||
limit = nodeStackPtr->limit;
|
||||
} else {
|
||||
Uint32 currentNode = *next++;
|
||||
Uint32 pushedList = 0;
|
||||
|
||||
|
||||
// Initialize the sets.
|
||||
pushed.clear();
|
||||
destinationList.clear();
|
||||
|
||||
// STEP1:
|
||||
// Walk the instruction list and to replace all the instruction uses with their new name.
|
||||
// If the instruction is a phi node and its defined register is alive at the end of this
|
||||
// block then we push the defined register into the stack.
|
||||
//
|
||||
ControlNode& node = *nodes[currentNode];
|
||||
RegisterPressure::Set* currentLiveOut = (liveOut != NULL) ? &liveOut[currentNode] : (RegisterPressure::Set*) 0;
|
||||
|
||||
InstructionList& phiNodes = node.getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& phiNode = phiNodes.get(p);
|
||||
|
||||
InstructionUse* useEnd = phiNode.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = phiNode.getInstructionUseBegin(); usePtr < useEnd; usePtr++) {
|
||||
assert(usePtr->isRegister());
|
||||
RegisterName name = usePtr->getRegisterName();
|
||||
|
||||
if (copyStats[name].newName != NULL && copyStats[name].newName->newName != name)
|
||||
usePtr->setRegisterName(copyStats[name].newName->newName);
|
||||
}
|
||||
|
||||
if (currentLiveOut != NULL) {
|
||||
// This is a phi node and we have to push its defined name if it is live
|
||||
// at the end of the node. We only need to do this if the CFG has critical edges.
|
||||
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd() && phiNode.getInstructionDefineBegin()[0].isRegister());
|
||||
RegisterName name = phiNode.getInstructionDefineBegin()[0].getRegisterName();
|
||||
|
||||
if (currentLiveOut->test(name))
|
||||
pushName(pool, &(copyStats[name].newName), pushed, &pushedList, name, name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName name = usePtr->getRegisterName();
|
||||
|
||||
if (copyStats[name].newName != NULL && copyStats[name].newName->newName != name)
|
||||
usePtr->setRegisterName(copyStats[name].newName->newName);
|
||||
}
|
||||
}
|
||||
|
||||
// STEP2:
|
||||
// Look at this node's successors' phiNodes. We keep track of the number of time
|
||||
// a VR will be used by another copy instruction and insert each definition into the
|
||||
// destinationList. This is the only pass over this node's successors as we will
|
||||
// get all the information we need in the CopyData structures.
|
||||
//
|
||||
ControlEdge* successorEdgeEnd = node.getSuccessorsEnd();
|
||||
for (ControlEdge* successorEdgePtr = node.getSuccessorsBegin(); successorEdgePtr < successorEdgeEnd; successorEdgePtr++) {
|
||||
Uint32 useIndex = successorEdgePtr->getIndex();
|
||||
ControlNode& successor = successorEdgePtr->getTarget();
|
||||
|
||||
// Look at its phi nodes. The phi nodes are at the top of the instruction list. We exit
|
||||
// as soon as we find an instruction which is not a phi node
|
||||
InstructionList& phiNodes = successor.getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& phiNode = phiNodes.get(p);
|
||||
|
||||
assert((phiNode.getInstructionUseBegin() + useIndex) < phiNode.getInstructionUseEnd());
|
||||
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd());
|
||||
|
||||
InstructionUse& source = phiNode.getInstructionUseBegin()[useIndex];
|
||||
InstructionDefine& destination = phiNode.getInstructionDefineBegin()[0];
|
||||
|
||||
assert(source.isRegister() && destination.isRegister());
|
||||
|
||||
RegisterName sourceName = source.getRegisterName();
|
||||
RegisterName destinationName = destination.getRegisterName();
|
||||
|
||||
// Get the correct name for the source.
|
||||
if (copyStats[sourceName].newName != NULL)
|
||||
sourceName = copyStats[sourceName].newName->newName;
|
||||
|
||||
// Update the CopyData structures.
|
||||
if ((sourceName != rnInvalid) && (sourceName != destinationName)) {
|
||||
copyStats[destinationName].source = sourceName;
|
||||
copyStats[destinationName].classKind = destination.getRegisterClass();
|
||||
copyStats[destinationName].isLiveOut = (currentLiveOut != NULL) ? currentLiveOut->test(destinationName) : false;
|
||||
copyStats[destinationName].sourceNameToUse = destinationName;
|
||||
copyStats[sourceName].sourceNameToUse = sourceName;
|
||||
copyStats[sourceName].useCount++;
|
||||
destinationList.set(destinationName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// STEP3:
|
||||
// Insert into the worklist only the destination registers that will be not used in
|
||||
// another copy instruction in this block.
|
||||
//
|
||||
assert(workList.getSize() == 0);
|
||||
for (SparseSet::iterator d = destinationList.begin(); !destinationList.done(d); d = destinationList.advance(d)) {
|
||||
Uint32 dest = destinationList.get(d);
|
||||
if (copyStats[dest].useCount == 0)
|
||||
workList.set(dest);
|
||||
}
|
||||
|
||||
// STEP4:
|
||||
// Insert the copy instructions.
|
||||
//
|
||||
Uint32 destinationListSize = destinationList.getSize();
|
||||
InstructionList::iterator endOfTheNode = instructions.end();
|
||||
|
||||
// Find the right place to insert the copy instructions.
|
||||
if (destinationListSize != 0)
|
||||
while (instructions.get(endOfTheNode).getFlags() & ifControl)
|
||||
endOfTheNode = instructions.retreat(endOfTheNode);
|
||||
|
||||
while (destinationListSize != 0) {
|
||||
while(workList.getSize()) {
|
||||
RegisterName destinationName = RegisterName(workList.getOne());
|
||||
RegisterName sourceName = copyStats[destinationName].source;
|
||||
|
||||
workList.clear(destinationName);
|
||||
if (copyStats[destinationName].isLiveOut && !copyStats[destinationName].temporaryName) {
|
||||
// Lost copy problem.
|
||||
copyStats[destinationName].isLiveOut = false;
|
||||
|
||||
RegisterName sourceName = destinationName;
|
||||
RegisterClassKind classKind = copyStats[sourceName].classKind;
|
||||
RegisterName destinationName = getName(vrManager.newVirtualRegister(classKind));
|
||||
assert(destinationName < maxNameCount);
|
||||
|
||||
copyStats[destinationName].classKind = classKind;
|
||||
copyStats[sourceName].useCount = 0;
|
||||
|
||||
// We need to insert a copy to a temporary register to keep the
|
||||
// source register valid at the end of the node defining it.
|
||||
// This copy will be inserted right after the phi node defining it.
|
||||
RegisterName from = copyStats[sourceName].sourceNameToUse;
|
||||
Instruction* definingPhiNode = vrManager.getVirtualRegister(from).getDefiningInstruction();
|
||||
assert(definingPhiNode && (definingPhiNode->getFlags() & ifPhiNode) != 0);
|
||||
|
||||
RegisterID fromID = buildRegisterID(from, classKind);
|
||||
RegisterID toID = buildRegisterID(destinationName, classKind);
|
||||
Instruction& copy = emitter.newCopy(*definingPhiNode->getPrimitive(), fromID, toID);
|
||||
vrManager.getVirtualRegister(destinationName).setDefiningInstruction(copy);
|
||||
definingPhiNode->getPrimitive()->getContainer()->getInstructions().addFirst(copy);
|
||||
|
||||
copyStats[sourceName].temporaryName = destinationName;
|
||||
copyStats[sourceName].sourceNameToUse = destinationName;
|
||||
pushName(pool, &(copyStats[sourceName].newName), pushed, &pushedList, sourceName, destinationName);
|
||||
}
|
||||
|
||||
// Insert the copy instruction at the end of the current node.
|
||||
RegisterName from = copyStats[sourceName].sourceNameToUse;
|
||||
|
||||
RegisterClassKind classKind = copyStats[destinationName].classKind;
|
||||
RegisterID fromID = buildRegisterID(from, classKind);
|
||||
RegisterID toID = buildRegisterID(destinationName, classKind);
|
||||
Instruction& copy = emitter.newCopy(*vrManager.getVirtualRegister(from).getDefiningInstruction()->getPrimitive(), fromID, toID);
|
||||
instructions.insertAfter(copy, endOfTheNode);
|
||||
endOfTheNode = instructions.advance(endOfTheNode);
|
||||
|
||||
copyStats[sourceName].useCount = 0;
|
||||
if (destinationList.test(sourceName) && copyStats[sourceName].isLiveOut)
|
||||
pushName(pool, &(copyStats[sourceName].newName), pushed, &pushedList, sourceName, destinationName);
|
||||
copyStats[sourceName].isLiveOut = false;
|
||||
copyStats[sourceName].sourceNameToUse = destinationName;
|
||||
|
||||
if (destinationList.test(sourceName))
|
||||
workList.set(sourceName);
|
||||
destinationList.clear(destinationName);
|
||||
}
|
||||
|
||||
destinationListSize = destinationList.getSize();
|
||||
if (destinationListSize != 0) {
|
||||
RegisterName sourceName = RegisterName(destinationList.getOne());
|
||||
RegisterName destinationName;
|
||||
|
||||
if (!copyStats[sourceName].temporaryName) {
|
||||
// Cycle problem.
|
||||
RegisterClassKind classKind = copyStats[sourceName].classKind;
|
||||
destinationName = getName(vrManager.newVirtualRegister(classKind));
|
||||
assert(destinationName < maxNameCount);
|
||||
|
||||
copyStats[destinationName].classKind = classKind;
|
||||
copyStats[sourceName].temporaryName = destinationName;
|
||||
|
||||
// Insert the copy instruction at the end of the current node.
|
||||
RegisterName from = copyStats[sourceName].sourceNameToUse;
|
||||
|
||||
RegisterID fromID = buildRegisterID(from, classKind);
|
||||
RegisterID toID = buildRegisterID(destinationName, classKind);
|
||||
Instruction& copy = emitter.newCopy(*vrManager.getVirtualRegister(from).getDefiningInstruction()->getPrimitive(), fromID, toID);
|
||||
vrManager.getVirtualRegister(destinationName).setDefiningInstruction(copy);
|
||||
instructions.insertAfter(copy, endOfTheNode);
|
||||
endOfTheNode = instructions.advance(endOfTheNode);
|
||||
} else
|
||||
destinationName = copyStats[sourceName].temporaryName;
|
||||
|
||||
copyStats[sourceName].useCount = 0;
|
||||
copyStats[sourceName].isLiveOut = false;
|
||||
copyStats[sourceName].sourceNameToUse = destinationName;
|
||||
pushName(pool, &(copyStats[sourceName].newName), pushed, &pushedList, sourceName, destinationName);
|
||||
|
||||
workList.set(sourceName);
|
||||
}
|
||||
}
|
||||
|
||||
nodeStackPtr->pushedList = pushedList;
|
||||
nodeStackPtr->next = next;
|
||||
nodeStackPtr->limit = limit;
|
||||
++nodeStackPtr;
|
||||
next = dGraph.getSuccessorsBegin(currentNode);
|
||||
limit = dGraph.getSuccessorsEnd(currentNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _PHI_NODE_REMOVER_H_
|
||||
155
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocator.cpp
Normal file
155
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocator.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "LogModule.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterPressure.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
#include "PhiNodeRemover.h"
|
||||
#include "LiveRange.h"
|
||||
#include "Liveness.h"
|
||||
#include "InterferenceGraph.h"
|
||||
#include "LiveRangeGraph.h"
|
||||
#include "Coalescing.h"
|
||||
#include "Spilling.h"
|
||||
#include "Coloring.h"
|
||||
#include "Splits.h"
|
||||
|
||||
class Pool;
|
||||
class ControlGraph;
|
||||
class VirtualRegisterManager;
|
||||
class InstructionEmitter;
|
||||
|
||||
UT_DEFINE_LOG_MODULE(RegAlloc);
|
||||
|
||||
void RegisterAllocator::allocateRegisters(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter)
|
||||
{
|
||||
// Insert the phi node instructions. We want to do this to have a single defined register per instruction.
|
||||
// If we keep the PhiNode (as a DataNode) and a PhiNode is of DoubleWordKind then we have to execute
|
||||
// some special code for the high word annotation.
|
||||
//
|
||||
RegisterAllocatorTools::insertPhiNodeInstructions(controlGraph, emitter);
|
||||
|
||||
// Perform some tests on the instruction graph.
|
||||
//
|
||||
DEBUG_ONLY(RegisterAllocatorTools::testTheInstructionGraph(controlGraph, vrManager));
|
||||
|
||||
// Replace the phi node instructions by their equivalent copy instructions.
|
||||
//
|
||||
PhiNodeRemover<LowRegisterPressure>::replacePhiNodes(controlGraph, vrManager, emitter);
|
||||
|
||||
// Do the register allocation.
|
||||
//
|
||||
RegisterAllocator registerAllocator(pool, controlGraph, vrManager, emitter);
|
||||
registerAllocator.doGraphColoring();
|
||||
}
|
||||
|
||||
void RegisterAllocator::doGraphColoring()
|
||||
{
|
||||
// Initialize the liverange map.
|
||||
//
|
||||
initLiveRanges();
|
||||
|
||||
// Build the live ranges. We do this to compress the number of RegisterNames
|
||||
// used in the insterference graph.
|
||||
//
|
||||
LiveRange<LowRegisterPressure>::build(*this);
|
||||
|
||||
// Remove unnecessary copies.
|
||||
//
|
||||
RegisterAllocatorTools::removeUnnecessaryCopies(*this);
|
||||
|
||||
for (Uint8 loop = 0; loop < 10; loop++) {
|
||||
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("********* RegisterAllocator loop %d *********\n", loop));
|
||||
|
||||
while(true) {
|
||||
// Build the interference graph.
|
||||
//
|
||||
iGraph.build();
|
||||
|
||||
// Coalesce the copy instructions.
|
||||
//
|
||||
if (!Coalescing<LowRegisterPressure>::coalesce(*this))
|
||||
break;
|
||||
}
|
||||
|
||||
// Print the interference graph.
|
||||
//
|
||||
DEBUG_LOG_ONLY(iGraph.printPretty(UT_LOG_MODULE(RegAlloc)));
|
||||
|
||||
// Calculate the spill costs.
|
||||
//
|
||||
Spilling<LowRegisterPressure>::calculateSpillCosts(*this);
|
||||
DEBUG_LOG_ONLY(RegisterAllocatorTools::printSpillCosts(*this));
|
||||
|
||||
// Calculate the split costs.
|
||||
//
|
||||
Splits<LowRegisterPressure>::calculateSplitCosts(*this);
|
||||
DEBUG_LOG_ONLY(RegisterAllocatorTools::printSplitCosts(*this));
|
||||
|
||||
// Build the live range graph.
|
||||
//
|
||||
lGraph.build();
|
||||
DEBUG_LOG_ONLY(lGraph.printPretty(UT_LOG_MODULE(RegAlloc)));
|
||||
|
||||
// Color the graph. If it succeeds then we're done with the
|
||||
// register allocation.
|
||||
//
|
||||
if (Coloring<LowRegisterPressure>::color(*this)) {
|
||||
// Write the final colors in the instruction graph.
|
||||
//
|
||||
Coloring<LowRegisterPressure>::finalColoring(*this);
|
||||
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("********** RegisterAllocator done **********\n"));
|
||||
DEBUG_LOG_ONLY(RegisterAllocatorTools::printInstructions(*this));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to spill some registers.
|
||||
//
|
||||
Spilling<LowRegisterPressure>::insertSpillCode(*this);
|
||||
|
||||
// Insert the split instructions.
|
||||
//
|
||||
Splits<LowRegisterPressure>::insertSplitCode(*this);
|
||||
|
||||
// Update the live ranges.
|
||||
//
|
||||
// FIX
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
RegisterAllocatorTools::updateInstructionGraph(*this);
|
||||
RegisterAllocatorTools::printInstructions(*this);
|
||||
#endif
|
||||
fprintf(stderr, "!!! Coloring failed after 10 loops !!!\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
void RegisterAllocator::initLiveRanges()
|
||||
{
|
||||
Uint32 count = this->nameCount;
|
||||
RegisterName* name2range = new(pool) RegisterName[nameCount];
|
||||
for (RegisterName r = RegisterName(1); r < count; r = RegisterName(r + 1))
|
||||
name2range[r] = r;
|
||||
this->name2range = name2range;
|
||||
rangeCount = count;
|
||||
}
|
||||
88
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocator.h
Normal file
88
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocator.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _REGISTER_ALLOCATOR_H_
|
||||
#define _REGISTER_ALLOCATOR_H_
|
||||
|
||||
class Pool;
|
||||
class ControlGraph;
|
||||
class InstructionEmitter;
|
||||
struct SpillCost;
|
||||
struct SplitCost;
|
||||
|
||||
#include "Liveness.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "RegisterPressure.h" // This should included by Backend.cpp
|
||||
#include "InterferenceGraph.h"
|
||||
#include "LiveRangeGraph.h"
|
||||
|
||||
//template <class RegisterPressure>
|
||||
class RegisterAllocator
|
||||
{
|
||||
public:
|
||||
|
||||
Pool& pool; //
|
||||
ControlGraph& controlGraph; //
|
||||
VirtualRegisterManager& vrManager; //
|
||||
InstructionEmitter& emitter; //
|
||||
|
||||
RegisterName* name2range; //
|
||||
RegisterName* color; //
|
||||
SpillCost* spillCost; //
|
||||
SparseSet* willSpill; //
|
||||
SplitCost* splitCost; //
|
||||
NameLinkedList** splitAround; //
|
||||
InterferenceGraph<LowRegisterPressure> iGraph; //
|
||||
LiveRangeGraph<LowRegisterPressure> lGraph; //
|
||||
LivenessInfo<LowRegisterPressure> liveness; //
|
||||
Uint32 nameCount; //
|
||||
Uint32 rangeCount; //
|
||||
bool splitFound; //
|
||||
|
||||
private:
|
||||
|
||||
//
|
||||
//
|
||||
void doGraphColoring();
|
||||
|
||||
public:
|
||||
|
||||
//
|
||||
//
|
||||
inline RegisterAllocator(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter);
|
||||
|
||||
//
|
||||
//
|
||||
bool canInterfere(RegisterName /*name1*/, RegisterName /*name2*/) const {return true;}
|
||||
|
||||
//
|
||||
//
|
||||
void initLiveRanges();
|
||||
|
||||
//
|
||||
//
|
||||
static void allocateRegisters(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter);
|
||||
};
|
||||
|
||||
//
|
||||
//
|
||||
inline RegisterAllocator::RegisterAllocator(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter)
|
||||
: pool(pool), controlGraph(controlGraph), vrManager(vrManager), emitter(emitter), iGraph(*this), lGraph(*this), nameCount(vrManager.getSize()) {}
|
||||
|
||||
#endif // _REGISTER_ALLOCATOR_H_
|
||||
|
||||
355
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocatorTools.cpp
Normal file
355
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocatorTools.cpp
Normal file
@@ -0,0 +1,355 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "LogModule.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
#include "Pool.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Primitives.h"
|
||||
#include "InstructionEmitter.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "Spilling.h"
|
||||
#include "Splits.h"
|
||||
#include "BitSet.h"
|
||||
|
||||
UT_EXTERN_LOG_MODULE(RegAlloc);
|
||||
|
||||
#ifdef DEBUG
|
||||
void RegisterAllocatorTools::testTheInstructionGraph(ControlGraph& controlGraph, VirtualRegisterManager& vrManager)
|
||||
{
|
||||
// Test the declared VirtualRegisters. The register allocator tries to condense the register universe.
|
||||
// Any gap in the VirtualRegister names will be a loss of efficiency !!!!
|
||||
|
||||
Uint32 nameCount = vrManager.getSize();
|
||||
BitSet registerSeen(controlGraph.pool, nameCount);
|
||||
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
registerSeen.set(usePtr->getRegisterName());
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
registerSeen.set(definePtr->getRegisterName());
|
||||
}
|
||||
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& instruction = phiNodes.get(p);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
registerSeen.set(usePtr->getRegisterName());
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
registerSeen.set(definePtr->getRegisterName());
|
||||
}
|
||||
}
|
||||
|
||||
bool renameRegisters = false;
|
||||
for (BitSet::iterator i = registerSeen.nextZero(0); !registerSeen.done(i); i = registerSeen.nextZero(i)) {
|
||||
renameRegisters = true;
|
||||
fprintf(stderr,
|
||||
"WARNING: The VirtualRegister vr%d has been allocated during CodeGeneration but\n"
|
||||
" is never used nor defined by any instruction in the instruction graph\n"
|
||||
" PLEASE FIX \n",
|
||||
i);
|
||||
}
|
||||
if (renameRegisters) {
|
||||
Instruction** definingInstruction = new Instruction*[nameCount];
|
||||
memset(definingInstruction, '\0', nameCount * sizeof(Instruction*));
|
||||
RegisterName* newName = new RegisterName[nameCount];
|
||||
memset(newName, '\0', nameCount * sizeof(RegisterName));
|
||||
RegisterName nextName = RegisterName(1);
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName name = usePtr->getRegisterName();
|
||||
if (newName[name] == rnInvalid) {
|
||||
newName[name] = nextName;
|
||||
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
|
||||
nextName = RegisterName(nextName + 1);
|
||||
}
|
||||
usePtr->setRegisterName(newName[name]);
|
||||
}
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName name = definePtr->getRegisterName();
|
||||
if (newName[name] == rnInvalid) {
|
||||
newName[name] = nextName;
|
||||
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
|
||||
nextName = RegisterName(nextName + 1);
|
||||
}
|
||||
definePtr->setRegisterName(newName[name]);
|
||||
}
|
||||
}
|
||||
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& instruction = phiNodes.get(p);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName name = usePtr->getRegisterName();
|
||||
if (newName[name] == rnInvalid) {
|
||||
newName[name] = nextName;
|
||||
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
|
||||
nextName = RegisterName(nextName + 1);
|
||||
}
|
||||
usePtr->setRegisterName(newName[name]);
|
||||
}
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName name = definePtr->getRegisterName();
|
||||
if (newName[name] == rnInvalid) {
|
||||
newName[name] = nextName;
|
||||
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
|
||||
nextName = RegisterName(nextName + 1);
|
||||
}
|
||||
definePtr->setRegisterName(newName[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vrManager.setSize(nextName);
|
||||
|
||||
for (RegisterName r = RegisterName(1); r < nextName; r = RegisterName(r + 1))
|
||||
vrManager.getVirtualRegister(r).definingInstruction = definingInstruction[r];
|
||||
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("RegisterMap:\n"));
|
||||
for (Uint32 i = 1; i < nameCount; i++)
|
||||
if (newName[i] != 0)
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tvr%d becomes vr%d.\n", i, newName[i]));
|
||||
else
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tvr%d is dead.\n", i));
|
||||
|
||||
|
||||
delete newName;
|
||||
delete definingInstruction;
|
||||
}
|
||||
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
void RegisterAllocatorTools::removeUnnecessaryCopies(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i);) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
i = instructions.advance(i);
|
||||
|
||||
if (instruction.getFlags() & ifCopy) {
|
||||
assert(instruction.getInstructionUseBegin() != instruction.getInstructionUseEnd() && instruction.getInstructionUseBegin()[0].isRegister());
|
||||
assert(instruction.getInstructionDefineBegin() != instruction.getInstructionDefineEnd() && instruction.getInstructionDefineBegin()[0].isRegister());
|
||||
|
||||
RegisterName source = name2range[instruction.getInstructionUseBegin()[0].getRegisterName()];
|
||||
RegisterName destination = name2range[instruction.getInstructionDefineBegin()[0].getRegisterName()];
|
||||
|
||||
if (source == destination)
|
||||
instruction.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RegisterAllocatorTools::updateInstructionGraph(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
usePtr->setRegisterName(name2range[usePtr->getRegisterName()]);
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
definePtr->setRegisterName(name2range[definePtr->getRegisterName()]);
|
||||
}
|
||||
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& instruction = phiNodes.get(p);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
usePtr->setRegisterName(name2range[usePtr->getRegisterName()]);
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
definePtr->setRegisterName(name2range[definePtr->getRegisterName()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RegisterAllocatorTools::insertPhiNodeInstructions(ControlGraph& controlGraph, InstructionEmitter& emitter)
|
||||
{
|
||||
Pool& pool = controlGraph.pool;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
DoublyLinkedList<PhiNode>& phiNodes = node.getPhiNodes();
|
||||
|
||||
if (!phiNodes.empty()) {
|
||||
|
||||
// Set the index of the incoming edges.
|
||||
Uint32 index = 0;
|
||||
const DoublyLinkedList<ControlEdge>& predecessors = node.getPredecessors();
|
||||
for (DoublyLinkedList<ControlEdge>::iterator p = predecessors.begin(); !predecessors.done(p); p = predecessors.advance(p))
|
||||
predecessors.get(p).setIndex(index++);
|
||||
|
||||
// Insert the phi node instruction in the instruction list.
|
||||
for (DoublyLinkedList<PhiNode>::iterator i = phiNodes.begin(); !phiNodes.done(i); i = phiNodes.advance(i)) {
|
||||
PhiNode& phiNode = phiNodes.get(i);
|
||||
ValueKind kind = phiNode.getKind();
|
||||
|
||||
if (!isStorableKind(kind))
|
||||
continue;
|
||||
|
||||
RegisterClassKind classKind = rckGeneral; // FIX: get class kind from phi node kind.
|
||||
Uint32 nInputs = phiNode.nInputs();
|
||||
|
||||
PhiNodeInstruction& phiNodeInstruction = *new(pool) PhiNodeInstruction(&phiNode, pool, nInputs);
|
||||
|
||||
emitter.defineProducer(phiNode, phiNodeInstruction, 0, classKind, drLow);
|
||||
for (Uint32 whichInput = 0; whichInput < nInputs; whichInput++)
|
||||
emitter.useProducer(phiNode.nthInputVariable(whichInput), phiNodeInstruction, whichInput, classKind, drLow);
|
||||
|
||||
node.addPhiNodeInstruction(phiNodeInstruction);
|
||||
|
||||
if (isDoublewordKind(kind)) {
|
||||
PhiNodeInstruction& phiNodeInstruction = *new(pool) PhiNodeInstruction(&phiNode, pool, nInputs);
|
||||
|
||||
emitter.defineProducer(phiNode, phiNodeInstruction, 0, classKind, drHigh);
|
||||
for (Uint32 whichInput = 0; whichInput < nInputs; whichInput++)
|
||||
emitter.useProducer(phiNode.nthInputVariable(whichInput), phiNodeInstruction, whichInput, classKind, drHigh);
|
||||
|
||||
node.addPhiNodeInstruction(phiNodeInstruction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
|
||||
void RegisterAllocatorTools::printSpillCosts(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
LogModuleObject log = UT_LOG_MODULE(RegAlloc);
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
SpillCost* cost = registerAllocator.spillCost;
|
||||
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Spill costs:\n"));
|
||||
for (Uint32 i = 1; i < rangeCount; i++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\trange %d : ", i));
|
||||
if (cost[i].infinite)
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("infinite\n"));
|
||||
else
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%f\n", cost[i].cost));
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterAllocatorTools::printSplitCosts(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
LogModuleObject log = UT_LOG_MODULE(RegAlloc);
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
SplitCost* cost = registerAllocator.splitCost;
|
||||
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Split costs:\n"));
|
||||
for (Uint32 i = 1; i < rangeCount; i++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\trange %d : loads = %f stores = %f\n", i, cost[i].loads, cost[i].stores));
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterAllocatorTools::printInstructions(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
LogModuleObject log = UT_LOG_MODULE(RegAlloc);
|
||||
ControlNode** nodes = registerAllocator.controlGraph.dfsList;
|
||||
Uint32 nNodes = registerAllocator.controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("N%d:\n", n));
|
||||
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
|
||||
if (!phiNodes.empty()) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" PhiNodes:\n", n));
|
||||
for(InstructionList::iterator i = phiNodes.begin(); !phiNodes.done(i); i = phiNodes.advance(i)) {
|
||||
phiNodes.get(i).printPretty(log);
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
if (!instructions.empty())
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" Instructions:\n", n));
|
||||
}
|
||||
|
||||
for(InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
instructions.get(i).printPretty(log);
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
117
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocatorTools.h
Normal file
117
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocatorTools.h
Normal file
@@ -0,0 +1,117 @@
|
||||
// -*- mode:C++; tab-width:4; truncate-lines:t -*-
|
||||
//
|
||||
// CONFIDENTIAL AND PROPRIETARY SOURCE CODE OF
|
||||
// NETSCAPE COMMUNICATIONS CORPORATION
|
||||
// Copyright © 1996, 1997 Netscape Communications Corporation. All Rights
|
||||
// Reserved. Use of this Source Code is subject to the terms of the
|
||||
// applicable license agreement from Netscape Communications Corporation.
|
||||
// The copyright notice(s) in this Source Code does not indicate actual or
|
||||
// intended publication of this Source Code.
|
||||
//
|
||||
// $Id: RegisterAllocatorTools.h,v 1.1.2.1 1999-03-02 16:12:05 fur%netscape.com Exp $
|
||||
//
|
||||
|
||||
#ifndef _REGISTER_ALLOCATOR_TOOLS_H_
|
||||
#define _REGISTER_ALLOCATOR_TOOLS_H_
|
||||
|
||||
#include "LogModule.h"
|
||||
#include "RegisterTypes.h"
|
||||
#include <string.h>
|
||||
|
||||
class RegisterAllocator;
|
||||
class ControlGraph;
|
||||
class InstructionEmitter;
|
||||
class VirtualRegisterManager;
|
||||
|
||||
struct RegisterAllocatorTools
|
||||
{
|
||||
//
|
||||
//
|
||||
static void insertPhiNodeInstructions(ControlGraph& controlGraph, InstructionEmitter& emitter);
|
||||
|
||||
//
|
||||
//
|
||||
static void updateInstructionGraph(RegisterAllocator& registerAllocator);
|
||||
|
||||
//
|
||||
//
|
||||
static void removeUnnecessaryCopies(RegisterAllocator& registerAllocator);
|
||||
|
||||
#ifdef DEBUG
|
||||
//
|
||||
//
|
||||
static void testTheInstructionGraph(ControlGraph& controlGraph, VirtualRegisterManager& vrManager);
|
||||
#endif // DEBUG
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
//
|
||||
//
|
||||
static void printInstructions(RegisterAllocator& registerAllocator);
|
||||
|
||||
//
|
||||
//
|
||||
static void printSpillCosts(RegisterAllocator& registerAllocator);
|
||||
|
||||
//
|
||||
//
|
||||
static void printSplitCosts(RegisterAllocator& registerAllocator);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
//
|
||||
// FIX: this should go in a class (LookupTable ?)
|
||||
//
|
||||
|
||||
inline RegisterName findRoot(RegisterName name, RegisterName* table)
|
||||
{
|
||||
RegisterName* stack = table;
|
||||
RegisterName* stackPtr = stack;
|
||||
|
||||
RegisterName newName;
|
||||
while((newName = table[name]) != name) {
|
||||
*--stackPtr = name;
|
||||
name = newName;
|
||||
}
|
||||
|
||||
while (stackPtr != stack)
|
||||
table[*stackPtr++] = name;
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
inline void init(RegisterName* table, Uint32 nameCount)
|
||||
{
|
||||
for (RegisterName r = RegisterName(0); r < nameCount; r = RegisterName(r + 1))
|
||||
table[r] = r;
|
||||
}
|
||||
|
||||
inline Uint32 compress(RegisterName* name2range, RegisterName* table, Uint32 nameCount, Uint32 tableSize)
|
||||
{
|
||||
RegisterName* liveRange = new RegisterName[tableSize];
|
||||
memset(liveRange, '\0', tableSize * sizeof(RegisterName));
|
||||
|
||||
// Update the lookup table.
|
||||
for (RegisterName r = RegisterName(1); r < tableSize; r = RegisterName(r + 1))
|
||||
findRoot(r, table);
|
||||
|
||||
// Count the liveranges.
|
||||
Uint32 liveRangeCount = 1;
|
||||
for (RegisterName s = RegisterName(1); s < tableSize; s = RegisterName(s + 1))
|
||||
if (table[s] == s)
|
||||
liveRange[s] = RegisterName(liveRangeCount++);
|
||||
|
||||
for (RegisterName t = RegisterName(1); t < nameCount; t = RegisterName(t + 1))
|
||||
name2range[t] = liveRange[table[name2range[t]]];
|
||||
|
||||
return liveRangeCount;
|
||||
}
|
||||
|
||||
inline double doLog10(Uint32 power)
|
||||
{
|
||||
double log = 1.0;
|
||||
while (power--)
|
||||
log *= 10.0;
|
||||
return log;
|
||||
}
|
||||
|
||||
#endif // _REGISTER_ALLOCATOR_TOOLS_H_
|
||||
38
mozilla/ef/Compiler/RegisterAllocator/RegisterAssigner.h
Normal file
38
mozilla/ef/Compiler/RegisterAllocator/RegisterAssigner.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _REGISTER_ASSIGNER_H_
|
||||
#define _REGISTER_ASSIGNER_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "VirtualRegister.h"
|
||||
|
||||
class FastBitMatrix;
|
||||
|
||||
class RegisterAssigner
|
||||
{
|
||||
protected:
|
||||
VirtualRegisterManager& vRegManager;
|
||||
|
||||
public:
|
||||
RegisterAssigner(VirtualRegisterManager& vrMan) : vRegManager(vrMan) {}
|
||||
|
||||
virtual bool assignRegisters(FastBitMatrix& interferenceMatrix) = 0;
|
||||
};
|
||||
|
||||
#endif /* _REGISTER_ASSIGNER_H_ */
|
||||
25
mozilla/ef/Compiler/RegisterAllocator/RegisterClass.h
Normal file
25
mozilla/ef/Compiler/RegisterAllocator/RegisterClass.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _REGISTER_CLASS_H_
|
||||
#define _REGISTER_CLASS_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "RegisterTypes.h"
|
||||
|
||||
#endif // _REGISTER_CLASS_H_
|
||||
37
mozilla/ef/Compiler/RegisterAllocator/RegisterPressure.h
Normal file
37
mozilla/ef/Compiler/RegisterAllocator/RegisterPressure.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _REGISTER_PRESSURE_H_
|
||||
#define _REGISTER_PRESSURE_H_
|
||||
|
||||
#include "BitSet.h"
|
||||
#include "HashSet.h"
|
||||
|
||||
struct LowRegisterPressure
|
||||
{
|
||||
typedef BitSet Set;
|
||||
static const bool setIsOrdered = true;
|
||||
};
|
||||
|
||||
struct HighRegisterPressure
|
||||
{
|
||||
typedef HashSet Set;
|
||||
static const bool setIsOrdered = false;
|
||||
};
|
||||
|
||||
#endif // _REGISTER_PRESSURE_H_
|
||||
104
mozilla/ef/Compiler/RegisterAllocator/RegisterTypes.h
Normal file
104
mozilla/ef/Compiler/RegisterAllocator/RegisterTypes.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _REGISTER_TYPES_H_
|
||||
#define _REGISTER_TYPES_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterName -
|
||||
//
|
||||
|
||||
enum RegisterName {
|
||||
rnInvalid = 0,
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterClassKind -
|
||||
//
|
||||
|
||||
enum RegisterClassKind {
|
||||
rckInvalid = 0,
|
||||
rckGeneral,
|
||||
rckStackSlot,
|
||||
|
||||
nRegisterClassKind
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterID -
|
||||
//
|
||||
|
||||
enum RegisterID {
|
||||
invalidID = 0
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterKind -
|
||||
//
|
||||
|
||||
enum RegisterKind {
|
||||
rkCallerSave = 0,
|
||||
rkCalleeSave,
|
||||
};
|
||||
|
||||
struct NameLinkedList {
|
||||
RegisterName name;
|
||||
NameLinkedList* next;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
const registerNameMask = 0x03ffffff;
|
||||
const coloredRegisterMask = 0x04000000;
|
||||
const machineRegisterMask = 0x08000000;
|
||||
const registerClassMask = 0xf0000000;
|
||||
|
||||
const registerNameShift = 0;
|
||||
const coloredRegisterShift = 26;
|
||||
const machineRegisterShift = 27;
|
||||
const registerClassShift = 28;
|
||||
|
||||
#else // DEBUG
|
||||
|
||||
const registerNameMask = 0x0fffffff;
|
||||
const registerClassMask = 0xf0000000;
|
||||
|
||||
const registerNameShift = 0;
|
||||
const registerClassShift = 28;
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
|
||||
inline RegisterClassKind getClass(RegisterID registerID) {return RegisterClassKind((registerID & registerClassMask) >> registerClassShift);}
|
||||
inline RegisterName getName(RegisterID registerID) {return RegisterName((registerID & registerNameMask) >> registerNameShift);}
|
||||
inline void setClass(RegisterID& registerID, RegisterClassKind classKind) {registerID = RegisterID((registerID & ~registerClassMask) | ((classKind << registerClassShift) & registerClassMask));}
|
||||
inline void setName(RegisterID& registerID, RegisterName name) {assert((name & ~registerNameMask) == 0); registerID = RegisterID((registerID & ~registerNameMask) | ((name << registerNameShift) & registerNameMask));}
|
||||
inline RegisterID buildRegisterID(RegisterName name, RegisterClassKind classKind) {return RegisterID(((classKind << registerClassShift) & registerClassMask) | ((name << registerNameShift) & registerNameMask));}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
inline bool isMachineRegister(RegisterID rid) {return (rid & machineRegisterMask) != 0;}
|
||||
inline void setMachineRegister(RegisterID& rid) {rid = RegisterID(rid | machineRegisterMask);}
|
||||
inline bool isColoredRegister(RegisterID rid) {return (rid & coloredRegisterMask) != 0;}
|
||||
inline void setColoredRegister(RegisterID& rid) {rid = RegisterID(rid | coloredRegisterMask);}
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
#endif // _REGISTER_TYPES_H_
|
||||
32
mozilla/ef/Compiler/RegisterAllocator/SSATools.cpp
Normal file
32
mozilla/ef/Compiler/RegisterAllocator/SSATools.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "SSATools.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "Liveness.h"
|
||||
|
||||
void replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager)
|
||||
{
|
||||
if (!controlGraph.hasBackEdges)
|
||||
return;
|
||||
|
||||
Liveness liveness(controlGraph.pool);
|
||||
liveness.buildLivenessAnalysis(controlGraph, vrManager);
|
||||
}
|
||||
29
mozilla/ef/Compiler/RegisterAllocator/SSATools.h
Normal file
29
mozilla/ef/Compiler/RegisterAllocator/SSATools.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _SSA_TOOLS_H_
|
||||
#define _SSA_TOOLS_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
|
||||
class ControlGraph;
|
||||
class VirtualRegisterManager;
|
||||
|
||||
extern void replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager);
|
||||
|
||||
#endif // _SSA_TOOLS_H_
|
||||
37
mozilla/ef/Compiler/RegisterAllocator/SparseSet.cpp
Normal file
37
mozilla/ef/Compiler/RegisterAllocator/SparseSet.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "SparseSet.h"
|
||||
#include "BitSet.h"
|
||||
#include "Pool.h"
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
// Print the set.
|
||||
//
|
||||
void SparseSet::printPretty(LogModuleObject log)
|
||||
{
|
||||
Pool pool;
|
||||
BitSet set(pool, universeSize);
|
||||
|
||||
for (Uint32 i = 0; i < count; i++)
|
||||
set.set(node[i].element);
|
||||
|
||||
set.printPretty(log);
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
168
mozilla/ef/Compiler/RegisterAllocator/SparseSet.h
Normal file
168
mozilla/ef/Compiler/RegisterAllocator/SparseSet.h
Normal file
@@ -0,0 +1,168 @@
|
||||
// -*- mode:C++; tab-width:4; truncate-lines:t -*-
|
||||
//
|
||||
// CONFIDENTIAL AND PROPRIETARY SOURCE CODE OF
|
||||
// NETSCAPE COMMUNICATIONS CORPORATION
|
||||
// Copyright © 1996, 1997 Netscape Communications Corporation. All Rights
|
||||
// Reserved. Use of this Source Code is subject to the terms of the
|
||||
// applicable license agreement from Netscape Communications Corporation.
|
||||
// The copyright notice(s) in this Source Code does not indicate actual or
|
||||
// intended publication of this Source Code.
|
||||
//
|
||||
// $Id: SparseSet.h,v 1.1.2.1 1999-03-02 16:12:07 fur%netscape.com Exp $
|
||||
//
|
||||
|
||||
#ifndef _SPARSE_SET_H_
|
||||
#define _SPARSE_SET_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include "LogModule.h"
|
||||
#include "BitSet.h"
|
||||
|
||||
class SparseSet
|
||||
{
|
||||
private:
|
||||
|
||||
struct Node {
|
||||
Uint32 element;
|
||||
Uint32 stackIndex;
|
||||
};
|
||||
|
||||
Node* node;
|
||||
Uint32 count;
|
||||
Uint32 universeSize;
|
||||
|
||||
private:
|
||||
|
||||
// No copy constructor.
|
||||
SparseSet(const SparseSet&);
|
||||
|
||||
// Check if the given set's universe is of the same size than this universe.
|
||||
void checkUniverseCompatibility(const SparseSet& set) const {assert(set.universeSize == universeSize);}
|
||||
// Check if pos is valid for this set's universe.
|
||||
void checkMember(Int32 pos) const {assert(pos >=0 && Uint32(pos) < universeSize);}
|
||||
|
||||
public:
|
||||
|
||||
SparseSet(Pool& pool, Uint32 universeSize) : universeSize(universeSize) {node = new(pool) Node[universeSize]; clear();}
|
||||
|
||||
// Clear the sparse set.
|
||||
void clear() {count = 0;}
|
||||
// Clear the element at index.
|
||||
inline void clear(Uint32 index);
|
||||
// Set the element at index.
|
||||
inline void set(Uint32 index);
|
||||
// Return true if the element at index is set.
|
||||
inline bool test(Uint32 index) const;
|
||||
// Union with the given sparse set.
|
||||
inline void or(const SparseSet& set);
|
||||
// Intersection with the given sparse set.
|
||||
inline void and(const SparseSet& set);
|
||||
// Difference with the given sparse set.
|
||||
inline void difference(const SparseSet& set);
|
||||
// Copy set.
|
||||
inline SparseSet& operator = (const SparseSet& set);
|
||||
inline SparseSet& operator = (const BitSet& set);
|
||||
// Return true if the sparse sets are identical.
|
||||
friend bool operator == (const SparseSet& set1, const SparseSet& set2);
|
||||
// Return true if the sparse sets are different.
|
||||
friend bool operator != (const SparseSet& set1, const SparseSet& set2);
|
||||
|
||||
// Logical operators.
|
||||
SparseSet& operator |= (const SparseSet& set) {or(set); return *this;}
|
||||
SparseSet& operator &= (const SparseSet& set) {and(set); return *this;}
|
||||
SparseSet& operator -= (const SparseSet& set) {difference(set); return *this;}
|
||||
|
||||
// Iterator to conform with the set API.
|
||||
typedef Int32 iterator;
|
||||
// Return the iterator for the first element of this set.
|
||||
iterator begin() const {return count - 1;}
|
||||
// Return the next iterator.
|
||||
iterator advance(iterator pos) const {return --pos;}
|
||||
// Return true if the iterator is at the end of the set.
|
||||
bool done(iterator pos) const {return pos < 0;}
|
||||
// Return the element for the given iterator;
|
||||
Uint32 get(iterator pos) const {return node[pos].element;}
|
||||
// Return one element of this set.
|
||||
Uint32 getOne() const {assert(count > 0); return node[0].element;}
|
||||
// Return the size of this set.
|
||||
Uint32 getSize() const {return count;}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
// Print the set.
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
inline void SparseSet::clear(Uint32 element)
|
||||
{
|
||||
checkMember(element);
|
||||
Uint32 count = this->count;
|
||||
Node* node = this->node;
|
||||
|
||||
Uint32 stackIndex = node[element].stackIndex;
|
||||
|
||||
if ((stackIndex < count) && (node[stackIndex].element == element)) {
|
||||
Uint32 stackTop = node[count - 1].element;
|
||||
|
||||
node[stackIndex].element = stackTop;
|
||||
node[stackTop].stackIndex = stackIndex;
|
||||
this->count = count - 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SparseSet::set(Uint32 element)
|
||||
{
|
||||
checkMember(element);
|
||||
Uint32 count = this->count;
|
||||
Node* node = this->node;
|
||||
|
||||
Uint32 stackIndex = node[element].stackIndex;
|
||||
|
||||
if ((stackIndex >= count) || (node[stackIndex].element != element)) {
|
||||
node[count].element = element;
|
||||
node[element].stackIndex = count;
|
||||
this->count = count + 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool SparseSet::test(Uint32 element) const
|
||||
{
|
||||
checkMember(element);
|
||||
Node* node = this->node;
|
||||
|
||||
Uint32 stackIndex = node[element].stackIndex;
|
||||
return ((stackIndex < count) && (node[stackIndex].element == element));
|
||||
}
|
||||
|
||||
inline SparseSet& SparseSet::operator = (const SparseSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
Uint32 sourceCount = set.getSize();
|
||||
Node* node = this->node;
|
||||
|
||||
memcpy(node, set.node, sourceCount * sizeof(Node));
|
||||
|
||||
for (Uint32 i = 0; i < sourceCount; i++) {
|
||||
Uint32 element = node[i].element;
|
||||
node[element].stackIndex = i;
|
||||
}
|
||||
|
||||
count = sourceCount;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
inline SparseSet& SparseSet::operator = (const BitSet& set)
|
||||
{
|
||||
// FIX: there's room for optimization here.
|
||||
assert(universeSize == set.getSize());
|
||||
|
||||
clear();
|
||||
for (Int32 i = set.firstOne(); i != -1; i = set.nextOne(i))
|
||||
this->set(i);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif // _SPARSE_SET_H_
|
||||
270
mozilla/ef/Compiler/RegisterAllocator/Spilling.cpp
Normal file
270
mozilla/ef/Compiler/RegisterAllocator/Spilling.cpp
Normal file
@@ -0,0 +1,270 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef NEW_LAURENTM_CODE
|
||||
#define INCLUDE_EMITTER
|
||||
#include "CpuInfo.h"
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "InstructionEmitter.h"
|
||||
#include "Spilling.h"
|
||||
|
||||
|
||||
void Spilling::
|
||||
insertSpillCode(ControlNode** dfsList, Uint32 nNodes)
|
||||
{
|
||||
PRUint32 nVirtualRegisters = vRegManager.count();
|
||||
FastBitSet currentLive(vRegManager.pool, nVirtualRegisters);
|
||||
FastBitSet usedInThisInstruction(vRegManager.pool, nVirtualRegisters);
|
||||
RegisterFifo grNeedLoad(nVirtualRegisters);
|
||||
RegisterFifo fpNeedLoad(nVirtualRegisters);
|
||||
|
||||
for (PRInt32 n = nNodes - 1; n >= 0; n--)
|
||||
{
|
||||
PR_ASSERT(grNeedLoad.empty() & fpNeedLoad.empty());
|
||||
ControlNode& node = *dfsList[n];
|
||||
|
||||
currentLive = node.liveAtEnd;
|
||||
|
||||
PRUint32 nGeneralAlive = 0;
|
||||
PRUint32 nFloatingPointAlive = 0;
|
||||
|
||||
// Get the number of registers alive at the end of this node.
|
||||
for (PRInt32 j = currentLive.firstOne(); j != -1; j = currentLive.nextOne(j))
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(j);
|
||||
if (vReg.spillInfo.willSpill)
|
||||
{
|
||||
currentLive.clear(j);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
nGeneralAlive++;
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
nFloatingPointAlive++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if(node.dfsNum == 8) printf("\n________Begin Node %d________\n", node.dfsNum);
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i))
|
||||
{
|
||||
Instruction& instruction = instructions.get(i);
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* defPtr;
|
||||
|
||||
// if(node.dfsNum == 8) { printf("\n");
|
||||
// instruction.printPretty(stdout);
|
||||
// printf("\n"); }
|
||||
|
||||
// Handle definitions
|
||||
for (defPtr = defBegin; defPtr < defEnd; defPtr++)
|
||||
if (defPtr->isVirtualRegister())
|
||||
{
|
||||
VirtualRegister& vReg = defPtr->getVirtualRegister();
|
||||
currentLive.clear(vReg.getRegisterIndex());
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
nGeneralAlive--;
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
nFloatingPointAlive--;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for deaths
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isVirtualRegister())
|
||||
{
|
||||
VirtualRegister& vReg = usePtr->getVirtualRegister();
|
||||
if (!currentLive.test(vReg.getRegisterIndex()))
|
||||
// This is the last use of this register.
|
||||
{
|
||||
currentLive.set(vReg.getRegisterIndex());
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
nGeneralAlive++;
|
||||
while (/*(nGeneralAlive > NUMBER_OF_GREGISTERS) &&*/ !grNeedLoad.empty())
|
||||
{
|
||||
PRUint32 toLoad = grNeedLoad.get();
|
||||
currentLive.clear(toLoad);
|
||||
nGeneralAlive--;
|
||||
|
||||
VirtualRegister& nReg = vRegManager.getVirtualRegister(toLoad);
|
||||
Instruction& lastUsingInstruction = *nReg.spillInfo.lastUsingInstruction;
|
||||
emitter.emitLoadAfter(*lastUsingInstruction.getPrimitive(), lastUsingInstruction.getLinks().prev,
|
||||
nReg.getAlias(), *nReg.equivalentRegister[vrcStackSlot]);
|
||||
nReg.releaseSelf();
|
||||
}
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
nFloatingPointAlive++;
|
||||
while (/*(nFloatingPointAlive > NUMBER_OF_FPREGISTERS) &&*/ !fpNeedLoad.empty())
|
||||
{
|
||||
PRUint32 toLoad = fpNeedLoad.get();
|
||||
currentLive.clear(toLoad);
|
||||
nFloatingPointAlive--;
|
||||
|
||||
VirtualRegister& nReg = vRegManager.getVirtualRegister(toLoad);
|
||||
Instruction& lastUsingInstruction = *nReg.spillInfo.lastUsingInstruction;
|
||||
emitter.emitLoadAfter(*lastUsingInstruction.getPrimitive(), lastUsingInstruction.getLinks().prev,
|
||||
nReg.getAlias(), *nReg.equivalentRegister[vrcStackSlot]);
|
||||
nReg.releaseSelf();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle uses
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isVirtualRegister())
|
||||
{
|
||||
VirtualRegister& vReg = usePtr->getVirtualRegister();
|
||||
PRUint32 registerIndex = vReg.getRegisterIndex();
|
||||
|
||||
if (vReg.spillInfo.willSpill) {
|
||||
#if defined(GENERATE_FOR_X86)
|
||||
if (!instruction.switchUseToSpill((usePtr - useBegin), *vReg.equivalentRegister[vrcStackSlot]))
|
||||
#endif
|
||||
{
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
if (!grNeedLoad.test(registerIndex))
|
||||
{
|
||||
grNeedLoad.put(registerIndex);
|
||||
VirtualRegister& alias = vRegManager.newVirtualRegister(vrcInteger);
|
||||
if (vReg.isPreColored())
|
||||
alias.preColorRegister(vReg.getPreColor());
|
||||
/* if (vReg.hasSpecialInterference) {
|
||||
alias.specialInterference.sizeTo(NUMBER_OF_REGISTERS);
|
||||
alias.specialInterference = vReg.specialInterference;
|
||||
alias.hasSpecialInterference = true;
|
||||
} */
|
||||
vReg.setAlias(alias);
|
||||
vReg.retainSelf();
|
||||
}
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
if (!fpNeedLoad.test(registerIndex))
|
||||
{
|
||||
fpNeedLoad.put(registerIndex);
|
||||
VirtualRegister& alias = vRegManager.newVirtualRegister(vReg.getClass());
|
||||
if (vReg.isPreColored())
|
||||
alias.preColorRegister(vReg.getPreColor());
|
||||
/*if (vReg.hasSpecialInterference) {
|
||||
alias.specialInterference.sizeTo(NUMBER_OF_REGISTERS);
|
||||
alias.specialInterference = vReg.specialInterference;
|
||||
alias.hasSpecialInterference = true;
|
||||
} */
|
||||
vReg.setAlias(alias);
|
||||
vReg.retainSelf();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
usePtr->getVirtualRegisterPtr().initialize(vReg.getAlias());
|
||||
usedInThisInstruction.set(registerIndex);
|
||||
vReg.spillInfo.lastUsingInstruction = &instruction;
|
||||
}
|
||||
currentLive.clear(registerIndex);
|
||||
} else { // will not spill
|
||||
currentLive.set(registerIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle definitions
|
||||
for (defPtr = defBegin; defPtr < defEnd; defPtr++)
|
||||
if (defPtr->isVirtualRegister())
|
||||
{
|
||||
VirtualRegister& vReg = defPtr->getVirtualRegister();
|
||||
|
||||
if (vReg.spillInfo.willSpill)
|
||||
#if defined(GENERATE_FOR_X86)
|
||||
if (!instruction.switchDefineToSpill((defPtr - defBegin), *vReg.equivalentRegister[vrcStackSlot]))
|
||||
#endif
|
||||
{
|
||||
if (usedInThisInstruction.test(vReg.getRegisterIndex()))
|
||||
// this virtualRegister was used in this instruction and is also defined. We need to move
|
||||
// this virtual register to its alias first and then save it to memory.
|
||||
{
|
||||
emitter.emitStoreAfter(*instruction.getPrimitive(), &instruction.getLinks(),
|
||||
vReg.getAlias(), *vReg.equivalentRegister[vrcStackSlot]);
|
||||
defPtr->getVirtualRegisterPtr().initialize(vReg.getAlias());
|
||||
}
|
||||
else
|
||||
{
|
||||
emitter.emitStoreAfter(*instruction.getPrimitive(), &instruction.getLinks(),
|
||||
vReg, *vReg.equivalentRegister[vrcStackSlot]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!grNeedLoad.empty())
|
||||
{
|
||||
PRUint32 nl = grNeedLoad.get();
|
||||
VirtualRegister& nlReg = vRegManager.getVirtualRegister(nl);
|
||||
Instruction& lastUse = *nlReg.spillInfo.lastUsingInstruction;
|
||||
|
||||
emitter.emitLoadAfter(*lastUse.getPrimitive(), lastUse.getLinks().prev,
|
||||
nlReg.getAlias(), *nlReg.equivalentRegister[vrcStackSlot]);
|
||||
nlReg.releaseSelf();
|
||||
}
|
||||
while (!fpNeedLoad.empty())
|
||||
{
|
||||
PRUint32 nl = fpNeedLoad.get();
|
||||
VirtualRegister& nlReg = vRegManager.getVirtualRegister(nl);
|
||||
Instruction& lastUse = *nlReg.spillInfo.lastUsingInstruction;
|
||||
|
||||
emitter.emitLoadAfter(*lastUse.getPrimitive(), lastUse.getLinks().prev,
|
||||
nlReg.getAlias(), *nlReg.equivalentRegister[vrcStackSlot]);
|
||||
nlReg.releaseSelf();
|
||||
}
|
||||
|
||||
// if(node.dfsNum == 8) printf("\n________End Node %d________\n", node.dfsNum);
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
269
mozilla/ef/Compiler/RegisterAllocator/Spilling.h
Normal file
269
mozilla/ef/Compiler/RegisterAllocator/Spilling.h
Normal file
@@ -0,0 +1,269 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _SPILLING_H_
|
||||
#define _SPILLING_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include <string.h>
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "SparseSet.h"
|
||||
|
||||
template <class RegisterPressure>
|
||||
class Spilling
|
||||
{
|
||||
private:
|
||||
static void insertStoreAfter(Instruction& instruction, RegisterName name);
|
||||
static void insertLoadBefore(Instruction& instruction, RegisterName name);
|
||||
|
||||
public:
|
||||
static void calculateSpillCosts(RegisterAllocator& registerAllocator);
|
||||
static void insertSpillCode(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
struct SpillCost
|
||||
{
|
||||
double loads;
|
||||
double stores;
|
||||
double copies;
|
||||
double cost;
|
||||
bool infinite;
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Spilling<RegisterPressure>::insertSpillCode(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
Pool& pool = registerAllocator.pool;
|
||||
SparseSet currentLive(pool, rangeCount);
|
||||
SparseSet needLoad(pool, rangeCount);
|
||||
SparseSet mustSpill(pool, rangeCount);
|
||||
SparseSet& willSpill = *registerAllocator.willSpill;
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
RegisterPressure::Set* liveOut = registerAllocator.liveness.liveOut;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
|
||||
needLoad.clear();
|
||||
currentLive = liveOut[n];
|
||||
mustSpill = currentLive;
|
||||
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i);) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
i = instructions.retreat(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
bool foundLiveDefine = false;
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
if (currentLive.test(name2range[definePtr->getRegisterName()])) {
|
||||
foundLiveDefine = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
foundLiveDefine = true;
|
||||
break;
|
||||
}
|
||||
if (defineBegin != defineEnd && !foundLiveDefine) {
|
||||
fprintf(stderr, "!!! Removed instruction because it was only defining unused registers !!!\n");
|
||||
instruction.remove();
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName range = name2range[definePtr->getRegisterName()];
|
||||
#ifdef DEBUG
|
||||
if (needLoad.test(range))
|
||||
if (!mustSpill.test(range) && registerAllocator.spillCost[range].infinite && willSpill.test(range)) {
|
||||
fprintf(stderr, "Tried to spill a register with infinite spill cost\n");
|
||||
abort();
|
||||
}
|
||||
#endif // DEBUG
|
||||
if (willSpill.test(range))
|
||||
insertStoreAfter(instruction, range);
|
||||
|
||||
needLoad.clear(range);
|
||||
}
|
||||
|
||||
if (instruction.getFlags() & ifCopy)
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName range = name2range[usePtr->getRegisterName()];
|
||||
if (!currentLive.test(range))
|
||||
for (SparseSet::iterator r = needLoad.begin(); !needLoad.done(r); r = needLoad.advance(r)) {
|
||||
RegisterName load = RegisterName(needLoad.get(r));
|
||||
if (willSpill.test(load))
|
||||
insertLoadBefore(instruction, load);
|
||||
mustSpill.set(load);
|
||||
}
|
||||
needLoad.clear();
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentLive.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName range = name2range[usePtr->getRegisterName()];
|
||||
currentLive.set(range);
|
||||
needLoad.set(range);
|
||||
}
|
||||
}
|
||||
|
||||
for (SparseSet::iterator l = needLoad.begin(); !needLoad.done(l); l = needLoad.advance(l)) {
|
||||
RegisterName load = RegisterName(needLoad.get(l));
|
||||
if (willSpill.test(load))
|
||||
insertLoadBefore(instructions.first(), load);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Spilling<RegisterPressure>::insertLoadBefore(Instruction& /*instruction*/, RegisterName name)
|
||||
{
|
||||
fprintf(stdout, "will insert load for range %d\n", name);
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Spilling<RegisterPressure>::insertStoreAfter(Instruction& /*instruction*/, RegisterName name)
|
||||
{
|
||||
fprintf(stdout, "will insert store for range %d\n", name);
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Spilling<RegisterPressure>::calculateSpillCosts(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
Pool& pool = registerAllocator.pool;
|
||||
SparseSet live(pool, rangeCount);
|
||||
SparseSet needLoad(pool, rangeCount);
|
||||
SparseSet mustSpill(pool, rangeCount);
|
||||
|
||||
SparseSet alreadyStored(pool, rangeCount); // FIX: should get this from previous spilling.
|
||||
|
||||
SpillCost* cost = new SpillCost[rangeCount];
|
||||
memset(cost, '\0', rangeCount * sizeof(SpillCost));
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
RegisterPressure::Set* liveOut = registerAllocator.liveness.liveOut;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
double weight = doLog10(node.loopDepth);
|
||||
|
||||
needLoad.clear();
|
||||
live = liveOut[n];
|
||||
mustSpill = live;
|
||||
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName range = name2range[definePtr->getRegisterName()];
|
||||
|
||||
if (needLoad.test(range))
|
||||
if (!mustSpill.test(range))
|
||||
cost[range].infinite = true;
|
||||
|
||||
if ((false /* !rematerializable(range) */ || !needLoad.test(range)) && !alreadyStored.test(range))
|
||||
cost[range].stores += weight;
|
||||
|
||||
needLoad.clear(range);
|
||||
}
|
||||
|
||||
if (instruction.getFlags() & ifCopy)
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
if (!live.test(name2range[usePtr->getRegisterName()])) {
|
||||
for (SparseSet::iterator l = needLoad.begin(); !needLoad.done(l); l = needLoad.advance(l)) {
|
||||
Uint32 range = needLoad.get(l);
|
||||
cost[range].loads += weight;
|
||||
mustSpill.set(range);
|
||||
}
|
||||
needLoad.clear();
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
live.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName range = name2range[usePtr->getRegisterName()];
|
||||
|
||||
live.set(range);
|
||||
needLoad.set(range);
|
||||
}
|
||||
|
||||
if (instruction.getFlags() & ifCopy) {
|
||||
assert(useBegin != useEnd && useBegin[0].isRegister());
|
||||
assert(defineBegin != defineEnd && defineBegin[0].isRegister());
|
||||
|
||||
RegisterName source = name2range[useBegin[0].getRegisterName()];
|
||||
RegisterName destination = name2range[defineBegin[0].getRegisterName()];
|
||||
|
||||
cost[source].copies += weight;
|
||||
cost[destination].copies += weight;
|
||||
}
|
||||
}
|
||||
|
||||
for (SparseSet::iterator s = needLoad.begin(); !needLoad.done(s); s = needLoad.advance(s))
|
||||
cost[needLoad.get(s)].loads += weight;
|
||||
}
|
||||
|
||||
for (Uint32 r = 0; r < rangeCount; r++) {
|
||||
SpillCost& c = cost[r];
|
||||
c.cost = 2 * (c.loads + c.stores) - c.copies;
|
||||
}
|
||||
|
||||
registerAllocator.spillCost = cost;
|
||||
}
|
||||
|
||||
#endif // _SPILLING_H_
|
||||
239
mozilla/ef/Compiler/RegisterAllocator/Splits.h
Normal file
239
mozilla/ef/Compiler/RegisterAllocator/Splits.h
Normal file
@@ -0,0 +1,239 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _SPLITS_H_
|
||||
#define _SPLITS_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include <string.h>
|
||||
#include "Pool.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
|
||||
UT_EXTERN_LOG_MODULE(RegAlloc);
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct Splits
|
||||
{
|
||||
static void calculateSplitCosts(RegisterAllocator& registerAllocator);
|
||||
static bool findSplit(RegisterAllocator& registerAllocator, RegisterName* color, RegisterName range);
|
||||
static void insertSplitCode(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
struct SplitCost
|
||||
{
|
||||
double loads;
|
||||
double stores;
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Splits<RegisterPressure>::insertSplitCode(RegisterAllocator& /*registerAllocator*/)
|
||||
{
|
||||
// FIX
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool Splits<RegisterPressure>::findSplit(RegisterAllocator& registerAllocator, RegisterName* color, RegisterName range)
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
NameLinkedList** neighborsWithColor = new(pool) NameLinkedList*[6]; // FIX
|
||||
memset(neighborsWithColor, '\0', 6 * sizeof(NameLinkedList*));
|
||||
|
||||
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
|
||||
|
||||
for (InterferenceVector* vector = iGraph.getInterferenceVector(range); vector != NULL; vector = vector->next)
|
||||
for (Int32 i = vector->count - 1; i >=0; --i) {
|
||||
RegisterName neighbor = vector->neighbors[i];
|
||||
RegisterName c = color[neighbor];
|
||||
|
||||
if (c < 6) { // FIX
|
||||
NameLinkedList* node = new(pool) NameLinkedList();
|
||||
node->name = neighbor;
|
||||
node->next = neighborsWithColor[c];
|
||||
neighborsWithColor[c] = node;
|
||||
}
|
||||
}
|
||||
|
||||
bool splitAroundName = true;
|
||||
|
||||
LiveRangeGraph<RegisterPressure>& lGraph = registerAllocator.lGraph;
|
||||
RegisterName bestColor = RegisterName(6); // FIX
|
||||
double bestCost = registerAllocator.spillCost[range].cost;
|
||||
SplitCost* splitCost = registerAllocator.splitCost;
|
||||
|
||||
for (RegisterName i = RegisterName(0); i < 6; i = RegisterName(i + 1)) { // FIX
|
||||
|
||||
double splitAroundNameCost = 0.0;
|
||||
bool canSplitAroundName = true;
|
||||
|
||||
SplitCost& sCost = splitCost[range];
|
||||
double addedCost = 2.0 * (sCost.stores + sCost.loads);
|
||||
|
||||
for (NameLinkedList* node = neighborsWithColor[i]; node != NULL; node = node->next) {
|
||||
RegisterName neighbor = node->name;
|
||||
if (lGraph.haveEdge(neighbor, range)) {
|
||||
canSplitAroundName = false;
|
||||
break;
|
||||
} else
|
||||
splitAroundNameCost += addedCost;
|
||||
}
|
||||
if (canSplitAroundName && splitAroundNameCost < bestCost) {
|
||||
bestCost = splitAroundNameCost;
|
||||
bestColor = i;
|
||||
splitAroundName = true;
|
||||
}
|
||||
|
||||
double splitAroundColorCost = 0.0;
|
||||
bool canSplitAroundColor = true;
|
||||
|
||||
for (NameLinkedList* node = neighborsWithColor[i]; node != NULL; node = node->next) {
|
||||
RegisterName neighbor = node->name;
|
||||
if (lGraph.haveEdge(range, neighbor)) {
|
||||
canSplitAroundColor = false;
|
||||
break;
|
||||
} else {
|
||||
SplitCost& sCost = splitCost[neighbor];
|
||||
double addedCost = 2.0 * (sCost.stores + sCost.loads);
|
||||
splitAroundColorCost += addedCost;
|
||||
}
|
||||
}
|
||||
if (canSplitAroundColor && splitAroundColorCost < bestCost) {
|
||||
bestCost = splitAroundColorCost;
|
||||
bestColor = i;
|
||||
splitAroundName = false;
|
||||
}
|
||||
}
|
||||
if (bestColor < RegisterName(6)) {
|
||||
color[range] = bestColor;
|
||||
registerAllocator.splitFound = true;
|
||||
|
||||
NameLinkedList** splitAround = registerAllocator.splitAround;
|
||||
|
||||
if (splitAroundName)
|
||||
for (NameLinkedList* node = neighborsWithColor[bestColor]; node != NULL; node = node->next) {
|
||||
NameLinkedList* newNode = new(pool) NameLinkedList();
|
||||
newNode->name = node->name;
|
||||
newNode->next = splitAround[range];
|
||||
splitAround[range] = newNode;
|
||||
}
|
||||
else
|
||||
for (NameLinkedList* node = neighborsWithColor[bestColor]; node != NULL; node = node->next) {
|
||||
NameLinkedList* newNode = new(pool) NameLinkedList();
|
||||
RegisterName neighbor = node->name;
|
||||
newNode->name = range;
|
||||
newNode->next = splitAround[neighbor];
|
||||
splitAround[neighbor] = newNode;
|
||||
}
|
||||
|
||||
trespass("Found a split");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Splits<RegisterPressure>::calculateSplitCosts(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
SplitCost* splitCost = new(pool) SplitCost[rangeCount];
|
||||
memset(splitCost, '\0', rangeCount * sizeof(SplitCost));
|
||||
|
||||
SparseSet live(pool, rangeCount);
|
||||
RegisterPressure::Set* liveIn = registerAllocator.liveness.liveIn;
|
||||
RegisterPressure::Set* liveOut = registerAllocator.liveness.liveOut;
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
double weight = doLog10(node.loopDepth);
|
||||
|
||||
live = liveOut[n];
|
||||
|
||||
ControlEdge* successorsEnd = node.getSuccessorsEnd();
|
||||
for (ControlEdge* successorsPtr = node.getSuccessorsBegin(); successorsPtr < successorsEnd; successorsPtr++) {
|
||||
ControlNode& successor = successorsPtr->getTarget();
|
||||
|
||||
if (successor.getControlKind() != ckEnd) {
|
||||
RegisterPressure::Set& successorLiveIn = liveIn[successor.dfsNum];
|
||||
|
||||
for (SparseSet::iterator i = live.begin(); !live.done(i); i = live.advance(i)) {
|
||||
RegisterName name = RegisterName(live.get(i));
|
||||
if (!successorLiveIn.test(name))
|
||||
splitCost[name].loads += doLog10(successor.loopDepth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
splitCost[name2range[definePtr->getRegisterName()]].stores += weight;
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName range = name2range[usePtr->getRegisterName()];
|
||||
if (!live.test(range)) {
|
||||
if (&instruction != &instructions.last())
|
||||
splitCost[range].loads += weight;
|
||||
else {
|
||||
ControlEdge* successorsEnd = node.getSuccessorsEnd();
|
||||
for (ControlEdge* successorsPtr = node.getSuccessorsBegin(); successorsPtr < successorsEnd; successorsPtr++)
|
||||
splitCost[range].loads += doLog10(successorsPtr->getTarget().loopDepth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
live.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
live.set(name2range[usePtr->getRegisterName()]);
|
||||
}
|
||||
}
|
||||
|
||||
NameLinkedList** splitAround = new(pool) NameLinkedList*[rangeCount];
|
||||
memset(splitAround, '\0', rangeCount * sizeof(NameLinkedList*));
|
||||
registerAllocator.splitAround = splitAround;
|
||||
|
||||
registerAllocator.splitCost = splitCost;
|
||||
registerAllocator.splitFound = false;
|
||||
}
|
||||
|
||||
#endif // _SPLITS_H_
|
||||
186
mozilla/ef/Compiler/RegisterAllocator/Timer.cpp
Normal file
186
mozilla/ef/Compiler/RegisterAllocator/Timer.cpp
Normal file
@@ -0,0 +1,186 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "HashTable.h"
|
||||
#include "Timer.h"
|
||||
#include "Pool.h"
|
||||
|
||||
static Pool pool; // Pool for the Timer class.
|
||||
static HashTable<TimerEntry*> timerEntries(pool); // Timers hashtable.
|
||||
|
||||
const nTimersInABlock = 128; // Number of timers in a block.
|
||||
static PRTime *timers = new(pool) PRTime[nTimersInABlock]; // A block of timers.
|
||||
static Uint8 nextTimer = 0; // nextAvailableTimer.
|
||||
|
||||
//
|
||||
// Calibrate the call to PR_Now().
|
||||
//
|
||||
static PRTime calibrate()
|
||||
{
|
||||
PRTime t = PR_Now();
|
||||
PRTime& a = *new(pool) PRTime();
|
||||
|
||||
// Call 10 times the PR_Now() function.
|
||||
a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now();
|
||||
a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now();
|
||||
t = (PR_Now() - t + 9) / 10;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static PRTime adjust = calibrate();
|
||||
|
||||
//
|
||||
// Return the named timer..
|
||||
//
|
||||
TimerEntry& Timer::getTimerEntry(const char* name)
|
||||
{
|
||||
if (!timerEntries.exists(name)) {
|
||||
TimerEntry* newEntry = new(pool) TimerEntry();
|
||||
newEntry->accumulator = 0;
|
||||
newEntry->running = false;
|
||||
timerEntries.add(name, newEntry);
|
||||
}
|
||||
|
||||
return *timerEntries[name];
|
||||
}
|
||||
|
||||
//
|
||||
// Return a reference to a new timer.
|
||||
//
|
||||
PRTime& Timer::getNewTimer()
|
||||
{
|
||||
if (nextTimer >= nTimersInABlock) {
|
||||
timers = new(pool) PRTime[nTimersInABlock];
|
||||
nextTimer = 0;
|
||||
}
|
||||
return timers[nextTimer++];
|
||||
}
|
||||
|
||||
static Uint32 timersAreFrozen = 0;
|
||||
|
||||
//
|
||||
// Start the named timer.
|
||||
//
|
||||
void Timer::start(const char* name)
|
||||
{
|
||||
if (timersAreFrozen)
|
||||
return;
|
||||
|
||||
freezeTimers();
|
||||
|
||||
TimerEntry& timer = getTimerEntry(name);
|
||||
PR_ASSERT(!timer.running);
|
||||
|
||||
timer.accumulator = 0;
|
||||
timer.running = true;
|
||||
timer.done = false;
|
||||
|
||||
unfreezeTimers();
|
||||
}
|
||||
|
||||
//
|
||||
// Stop the named timer.
|
||||
//
|
||||
void Timer::stop(const char* name)
|
||||
{
|
||||
if (timersAreFrozen)
|
||||
return;
|
||||
|
||||
freezeTimers();
|
||||
|
||||
TimerEntry& timer = getTimerEntry(name);
|
||||
PR_ASSERT(timer.running);
|
||||
timer.running = false;
|
||||
timer.done = true;
|
||||
|
||||
unfreezeTimers();
|
||||
}
|
||||
|
||||
//
|
||||
// Freeze all the running timers.
|
||||
//
|
||||
void Timer::freezeTimers()
|
||||
{
|
||||
PRTime when = PR_Now() - adjust;
|
||||
|
||||
if (timersAreFrozen == 0) {
|
||||
Vector<TimerEntry*> entries = timerEntries;
|
||||
Uint32 count = entries.size();
|
||||
|
||||
for (Uint32 i = 0; i < count; i++) {
|
||||
TimerEntry& entry = *entries[i];
|
||||
if (entry.running) {
|
||||
entry.accumulator += (when - *entry.startTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
timersAreFrozen++;
|
||||
}
|
||||
|
||||
//
|
||||
// Unfreeze all the running timers.
|
||||
//
|
||||
void Timer::unfreezeTimers()
|
||||
{
|
||||
PR_ASSERT(timersAreFrozen != 0);
|
||||
timersAreFrozen--;
|
||||
|
||||
if (timersAreFrozen == 0) {
|
||||
Vector<TimerEntry *> entries = timerEntries;
|
||||
Uint32 count = entries.size();
|
||||
|
||||
PRTime& newStart = getNewTimer();
|
||||
|
||||
for (Uint32 i = 0; i < count; i++) {
|
||||
TimerEntry& entry = *entries[i];
|
||||
if (entry.running) {
|
||||
entry.startTime = &newStart;
|
||||
}
|
||||
}
|
||||
|
||||
newStart = PR_Now();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Print the named timer in the file f.
|
||||
//
|
||||
void Timer::print(FILE* f, const char *name)
|
||||
{
|
||||
if (timersAreFrozen)
|
||||
return;
|
||||
|
||||
freezeTimers();
|
||||
|
||||
TimerEntry& timer = getTimerEntry(name);
|
||||
|
||||
PR_ASSERT(timer.done);
|
||||
PRTime elapsed = timer.accumulator;
|
||||
|
||||
if (elapsed >> 32) {
|
||||
fprintf(f, "[timer %s out of range]\n", name);
|
||||
} else {
|
||||
fprintf(f, "[%dus in %s]\n", Uint32(elapsed), name);
|
||||
}
|
||||
fflush(f);
|
||||
|
||||
unfreezeTimers();
|
||||
}
|
||||
|
||||
80
mozilla/ef/Compiler/RegisterAllocator/Timer.h
Normal file
80
mozilla/ef/Compiler/RegisterAllocator/Timer.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _TIMER_H_
|
||||
#define _TIMER_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "HashTable.h"
|
||||
#include "prtime.h"
|
||||
|
||||
//
|
||||
// Naming convention:
|
||||
// As the class Timer contains only static methods, the timer's name should start with the
|
||||
// module name. Otherwise starting 2 timers with the same name will assert.
|
||||
//
|
||||
|
||||
#ifndef NO_TIMER
|
||||
|
||||
struct TimerEntry
|
||||
{
|
||||
PRTime *startTime; // Current time when we start the timer.
|
||||
PRTime accumulator; // Time spent in this timer.
|
||||
bool running; // True if the timer is running.
|
||||
bool done; // True if the timer was running and was stopped.
|
||||
};
|
||||
|
||||
class Timer
|
||||
{
|
||||
private:
|
||||
|
||||
// Return the named timer.
|
||||
static TimerEntry& getTimerEntry(const char* name);
|
||||
// Return a reference to a new Timer.
|
||||
static PRTime& getNewTimer();
|
||||
|
||||
public:
|
||||
|
||||
// Start the timer.
|
||||
static void start(const char* name);
|
||||
// Stop the timer.
|
||||
static void stop(const char* name);
|
||||
// Freeze all the running timers.
|
||||
static void freezeTimers();
|
||||
// Unfreeze all the running timers.
|
||||
static void unfreezeTimers();
|
||||
// Print the timer.
|
||||
static void print(FILE* f, const char *name);
|
||||
};
|
||||
|
||||
inline void startTimer(const char* name) {Timer::start(name);}
|
||||
inline void stopTimer(const char* name) {Timer::stop(name); Timer::print(stdout, name);}
|
||||
#define START_TIMER_SAFE Timer::freezeTimers();
|
||||
#define END_TIMER_SAFE Timer::unfreezeTimers();
|
||||
#define TIMER_SAFE(x) START_TIMER_SAFE x; END_TIMER_SAFE
|
||||
|
||||
#else /* NO_TIMER */
|
||||
|
||||
inline void startTimer(const char* /*name*/) {}
|
||||
inline void stopTimer(const char* /*name*/) {}
|
||||
#define START_TIMER_SAFE
|
||||
#define END_TIMER_SAFE
|
||||
#define TIMER_SAFE(x) x;
|
||||
|
||||
#endif /* NO_TIMER */
|
||||
#endif /* _TIMER_H_ */
|
||||
40
mozilla/ef/Compiler/RegisterAllocator/VirtualRegister.cpp
Normal file
40
mozilla/ef/Compiler/RegisterAllocator/VirtualRegister.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "Instruction.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// VirtualRegister -
|
||||
|
||||
#ifdef MANUAL_TEMPLATES
|
||||
template class IndexedPool<VirtualRegister>;
|
||||
#endif
|
||||
|
||||
// Set the defining instruction.
|
||||
//
|
||||
void VirtualRegister::setDefiningInstruction(Instruction& instruction)
|
||||
{
|
||||
if (definingInstruction != NULL) {
|
||||
if ((instruction.getFlags() & ifCopy) && (definingInstruction->getFlags() & ifPhiNode))
|
||||
return;
|
||||
}
|
||||
definingInstruction = &instruction;
|
||||
}
|
||||
|
||||
116
mozilla/ef/Compiler/RegisterAllocator/VirtualRegister.h
Normal file
116
mozilla/ef/Compiler/RegisterAllocator/VirtualRegister.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _VIRTUAL_REGISTER_H_
|
||||
#define _VIRTUAL_REGISTER_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "IndexedPool.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "RegisterTypes.h"
|
||||
#include "RegisterClass.h"
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// VirtualRegister - 24b
|
||||
|
||||
class Instruction;
|
||||
|
||||
class VirtualRegister : public IndexedObject<VirtualRegister>
|
||||
{
|
||||
public:
|
||||
|
||||
Instruction* definingInstruction; // Instruction defining this VR.
|
||||
|
||||
// Initialize a VR of the given classKind.
|
||||
VirtualRegister(RegisterClassKind /*classKind*/) : definingInstruction(NULL) {}
|
||||
|
||||
// Return the defining instruction for this VR.
|
||||
Instruction* getDefiningInstruction() const {return definingInstruction;}
|
||||
// Set the defining instruction.
|
||||
void setDefiningInstruction(Instruction& insn);
|
||||
};
|
||||
|
||||
// Return true if the VirtualRegisters are equals. The only way 2 VRs can be equal is if
|
||||
// they have the same index. If they have the same index then they are at the same
|
||||
// address in the indexed pool.
|
||||
//
|
||||
inline bool operator == (const VirtualRegister& regA, const VirtualRegister& regB) {return ®A == ®B;}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// VirtualRegisterManager -
|
||||
|
||||
struct PreColoredRegister
|
||||
{
|
||||
RegisterID id;
|
||||
RegisterName color;
|
||||
};
|
||||
|
||||
class VirtualRegisterManager
|
||||
{
|
||||
private:
|
||||
|
||||
IndexedPool<VirtualRegister> registerPool;
|
||||
PreColoredRegister machineRegister[6];
|
||||
|
||||
public:
|
||||
VirtualRegisterManager()
|
||||
{
|
||||
for (Uint32 i = 0; i < 6; i++)
|
||||
machineRegister[i].id = invalidID;
|
||||
}
|
||||
|
||||
// Return the VirtualRegister at the given index.
|
||||
VirtualRegister& getVirtualRegister(RegisterName name) const {return registerPool.get(name);}
|
||||
|
||||
// Return a new VirtualRegister.
|
||||
RegisterID newVirtualRegister(RegisterClassKind classKind)
|
||||
{
|
||||
VirtualRegister& vReg = *new(registerPool) VirtualRegister(classKind);
|
||||
RegisterID rid;
|
||||
|
||||
setName(rid, RegisterName(vReg.getIndex()));
|
||||
setClass(rid, classKind);
|
||||
return rid;
|
||||
}
|
||||
|
||||
RegisterID newMachineRegister(RegisterName name, RegisterClassKind classKind)
|
||||
{
|
||||
RegisterID rid = machineRegister[name].id;
|
||||
|
||||
if (rid == invalidID) {
|
||||
rid = newVirtualRegister(classKind);
|
||||
DEBUG_ONLY(setMachineRegister(rid));
|
||||
machineRegister[name].id = rid;
|
||||
machineRegister[name].color = name;
|
||||
}
|
||||
|
||||
return rid;
|
||||
}
|
||||
|
||||
PreColoredRegister* getMachineRegistersBegin() const {return (PreColoredRegister*) machineRegister;} // FIX
|
||||
PreColoredRegister* getMachineRegistersEnd() const {return (PreColoredRegister*) &machineRegister[6];} // FIX
|
||||
|
||||
// Return the VirtualRegister universe size.
|
||||
Uint32 getSize() {return registerPool.getSize();}
|
||||
|
||||
void setSize(Uint32 size) {registerPool.setSize(size);}
|
||||
};
|
||||
|
||||
#endif // _VIRTUAL_REGISTER_H_
|
||||
@@ -1,173 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
|
||||
#######################################################################
|
||||
# (1) Include initial platform-independent assignments (MANDATORY). #
|
||||
#######################################################################
|
||||
|
||||
include manifest.mn
|
||||
|
||||
#######################################################################
|
||||
# (2) Include "global" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/config.mk
|
||||
|
||||
#######################################################################
|
||||
# (3) Include "component" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
ifeq ($(OS_TARGET),WINCE)
|
||||
DIRS = lib # omit cmd since wince has no command line shell
|
||||
endif
|
||||
|
||||
#######################################################################
|
||||
# (5) Execute "global" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/rules.mk
|
||||
|
||||
#######################################################################
|
||||
# (6) Execute "component" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (7) Execute "local" rules. (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
nss_build_all: build_coreconf build_nspr build_dbm all
|
||||
|
||||
build_coreconf:
|
||||
cd $(CORE_DEPTH)/coreconf ; $(MAKE)
|
||||
|
||||
NSPR_CONFIG_STATUS = $(CORE_DEPTH)/../nsprpub/$(OBJDIR_NAME)/config.status
|
||||
NSPR_CONFIGURE = $(CORE_DEPTH)/../nsprpub/configure
|
||||
|
||||
#
|
||||
# Translate coreconf build options to NSPR configure options.
|
||||
#
|
||||
|
||||
ifdef BUILD_OPT
|
||||
NSPR_CONFIGURE_OPTS += --disable-debug --enable-optimize
|
||||
endif
|
||||
ifdef USE_64
|
||||
NSPR_CONFIGURE_OPTS += --enable-64bit
|
||||
endif
|
||||
ifeq ($(OS_TARGET),WIN95)
|
||||
NSPR_CONFIGURE_OPTS += --enable-win32-target=WIN95
|
||||
endif
|
||||
ifdef USE_DEBUG_RTL
|
||||
NSPR_CONFIGURE_OPTS += --enable-debug-rtl
|
||||
endif
|
||||
ifdef NS_USE_GCC
|
||||
NSPR_COMPILERS = CC=gcc CXX=g++
|
||||
endif
|
||||
|
||||
#
|
||||
# Some pwd commands on Windows (for example, the pwd
|
||||
# command in Cygwin) return a pathname that begins
|
||||
# with a (forward) slash. When such a pathname is
|
||||
# passed to Windows build tools (for example, cl), it
|
||||
# is mistaken as a command-line option. If that is the case,
|
||||
# we use a relative pathname as NSPR's prefix on Windows.
|
||||
#
|
||||
|
||||
USEABSPATH="YES"
|
||||
ifeq (,$(filter-out WIN%,$(OS_TARGET)))
|
||||
ifeq (,$(findstring :,$(shell pwd)))
|
||||
USEABSPATH="NO"
|
||||
endif
|
||||
endif
|
||||
ifeq ($(USEABSPATH),"YES")
|
||||
NSPR_PREFIX = $(shell pwd)/../../dist/$(OBJDIR_NAME)
|
||||
else
|
||||
NSPR_PREFIX = $$(topsrcdir)/../dist/$(OBJDIR_NAME)
|
||||
endif
|
||||
|
||||
$(NSPR_CONFIG_STATUS): $(NSPR_CONFIGURE)
|
||||
$(NSINSTALL) -D $(CORE_DEPTH)/../nsprpub/$(OBJDIR_NAME)
|
||||
cd $(CORE_DEPTH)/../nsprpub/$(OBJDIR_NAME) ; \
|
||||
$(NSPR_COMPILERS) sh ../configure \
|
||||
$(NSPR_CONFIGURE_OPTS) \
|
||||
--with-dist-prefix='$(NSPR_PREFIX)' \
|
||||
--with-dist-includedir='$(NSPR_PREFIX)/include'
|
||||
|
||||
build_nspr: $(NSPR_CONFIG_STATUS)
|
||||
cd $(CORE_DEPTH)/../nsprpub/$(OBJDIR_NAME) ; $(MAKE)
|
||||
|
||||
build_dbm:
|
||||
cd $(CORE_DEPTH)/dbm ; $(MAKE) export libs
|
||||
|
||||
|
||||
|
||||
moz_import::
|
||||
ifeq (,$(filter-out WIN%,$(OS_TARGET)))
|
||||
$(NSINSTALL) -D $(DIST)/include/nspr
|
||||
cp $(DIST)/../include/nspr/*.h $(DIST)/include/nspr
|
||||
cp $(DIST)/../include/* $(DIST)/include
|
||||
ifdef BUILD_OPT
|
||||
cp $(DIST)/../WIN32_O.OBJ/lib/* $(DIST)/lib
|
||||
else
|
||||
cp $(DIST)/../WIN32_D.OBJ/lib/* $(DIST)/lib
|
||||
endif
|
||||
mv $(DIST)/lib/dbm32.lib $(DIST)/lib/dbm.lib
|
||||
else
|
||||
ifeq ($(OS_TARGET),OS2)
|
||||
cp -rf $(DIST)/../include $(DIST)
|
||||
cp -rf $(DIST)/../lib $(DIST)
|
||||
cp -f $(DIST)/lib/libmozdbm_s.$(LIB_SUFFIX) $(DIST)/lib/libdbm.$(LIB_SUFFIX)
|
||||
else
|
||||
$(NSINSTALL) -L ../../dist include $(DIST)
|
||||
$(NSINSTALL) -L ../../dist lib $(DIST)
|
||||
cp $(DIST)/lib/libmozdbm_s.$(LIB_SUFFIX) $(DIST)/lib/libdbm.$(LIB_SUFFIX)
|
||||
endif
|
||||
endif
|
||||
|
||||
nss_RelEng_bld: build_coreconf import all
|
||||
|
||||
ifeq ($(OS_ARCH),SunOS)
|
||||
solarispkg:
|
||||
@echo Making Solaris packages.
|
||||
rm -rf pkg/$(OBJDIR)
|
||||
cp -r pkg/solaris pkg/$(OBJDIR)
|
||||
$(MAKE) -C pkg/$(OBJDIR) publish
|
||||
endif
|
||||
@@ -1,182 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
|
||||
CORE_DEPTH = ../..
|
||||
DEPTH = ../..
|
||||
|
||||
include manifest.mn
|
||||
include $(CORE_DEPTH)/coreconf/config.mk
|
||||
|
||||
# These sources were once in this directory, but now are gone.
|
||||
MISSING_SOURCES = \
|
||||
addcert.c \
|
||||
berparse.c \
|
||||
cert.c \
|
||||
key.c \
|
||||
key_rand.c \
|
||||
keygen.c \
|
||||
sec_fe.c \
|
||||
sec_read.c \
|
||||
secarb.c \
|
||||
secutil.c \
|
||||
$(NULL)
|
||||
|
||||
# we don't build these any more, but the sources are still here
|
||||
OBSOLETE = \
|
||||
berdec.c \
|
||||
berdump.c \
|
||||
cypher.c \
|
||||
dumpcert.c \
|
||||
listcerts.c \
|
||||
mkdongle.c \
|
||||
p12exprt.c \
|
||||
p12imprt.c \
|
||||
rc4.c \
|
||||
sign.c \
|
||||
unwrap.c \
|
||||
vector.c \
|
||||
verify.c \
|
||||
wrap.c \
|
||||
$(NULL)
|
||||
|
||||
# the base files for the executables
|
||||
# hey -- keep these alphabetical, please
|
||||
EXEC_SRCS = \
|
||||
$(NULL)
|
||||
|
||||
# files that generate two separate objects and executables
|
||||
# BI_SRCS = \
|
||||
# keyutil.c \
|
||||
# p7env.c \
|
||||
# tstclnt.c \
|
||||
# $(NULL)
|
||||
|
||||
# -I$(CORE_DEPTH)/security/lib/cert \
|
||||
# -I$(CORE_DEPTH)/security/lib/key \
|
||||
# -I$(CORE_DEPTH)/security/lib/util \
|
||||
|
||||
INCLUDES += \
|
||||
-I$(DIST)/../public/security \
|
||||
-I./include \
|
||||
$(NULL)
|
||||
|
||||
TBD_DIRS = rsh rshd rdist ssld
|
||||
|
||||
# For the time being, sec stuff is export only
|
||||
# US_FLAGS = -DEXPORT_VERSION -DUS_VERSION
|
||||
|
||||
US_FLAGS = -DEXPORT_VERSION
|
||||
EXPORT_FLAGS = -DEXPORT_VERSION
|
||||
|
||||
BASE_LIBS = \
|
||||
$(DIST)/lib/libdbm.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/libxp.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/libnspr.$(LIB_SUFFIX) \
|
||||
$(NULL)
|
||||
|
||||
# $(DIST)/lib/libpurenspr.$(LIB_SUFFIX) \
|
||||
|
||||
#There is a circular dependancy in security/lib, and here is a gross fix
|
||||
SEC_LIBS = \
|
||||
$(DIST)/lib/libsecnav.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/libssl.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/libpkcs7.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/libcert.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/libkey.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/libsecmod.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/libcrypto.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/libsecutil.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/libssl.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/libpkcs7.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/libcert.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/libkey.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/libsecmod.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/libcrypto.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/libsecutil.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/libhash.$(LIB_SUFFIX) \
|
||||
$(NULL)
|
||||
|
||||
MYLIB = lib/$(OBJDIR)/libsectool.$(LIB_SUFFIX)
|
||||
|
||||
US_LIBS = $(MYLIB) $(SEC_LIBS) $(BASE_LIBS) $(MYLIB) $(BASE_LIBS)
|
||||
EX_LIBS = $(MYLIB) $(SEC_LIBS) $(BASE_LIBS) $(MYLIB) $(BASE_LIBS)
|
||||
|
||||
REQUIRES = libxp nspr security
|
||||
|
||||
CSRCS = $(EXEC_SRCS) $(BI_SRCS)
|
||||
|
||||
OBJS = $(CSRCS:.c=.o) $(BI_SRCS:.c=-us.o) $(BI_SRCS:.c=-ex.o)
|
||||
|
||||
PROGS = $(addprefix $(OBJDIR)/, $(EXEC_SRCS:.c=$(BIN_SUFFIX)))
|
||||
US_PROGS = $(addprefix $(OBJDIR)/, $(BI_SRCS:.c=-us$(BIN_SUFFIX)))
|
||||
EX_PROGS = $(addprefix $(OBJDIR)/, $(BI_SRCS:.c=-ex$(BIN_SUFFIX)))
|
||||
|
||||
|
||||
NON_DIRS = $(PROGS) $(US_PROGS) $(EX_PROGS)
|
||||
TARGETS = $(NON_DIRS)
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/rules.mk
|
||||
|
||||
|
||||
ifneq ($(OS_TARGET),OS2)
|
||||
$(OBJDIR)/%-us.o: %.c
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CCF) -o $@ $(US_FLAGS) -c $*.c
|
||||
|
||||
$(OBJDIR)/%-ex.o: %.c
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CCF) -o $@ $(EXPORT_FLAGS) -c $*.c
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CCF) -o $@ $(EXPORT_FLAGS) -c $*.c
|
||||
|
||||
$(US_PROGS):$(OBJDIR)/%-us: $(OBJDIR)/%-us.o $(US_LIBS)
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CCF) -o $@ $(OBJDIR)/$*-us.o $(LDFLAGS) $(US_LIBS) $(OS_LIBS)
|
||||
|
||||
$(EX_PROGS):$(OBJDIR)/%-ex: $(OBJDIR)/%-ex.o $(EX_LIBS)
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CCF) -o $@ $(OBJDIR)/$*-ex.o $(LDFLAGS) $(EX_LIBS) $(OS_LIBS)
|
||||
|
||||
$(PROGS):$(OBJDIR)/%: $(OBJDIR)/%.o $(EX_LIBS)
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CCF) -o $@ $@.o $(LDFLAGS) $(EX_LIBS) $(OS_LIBS)
|
||||
|
||||
#install:: $(TARGETS)
|
||||
# $(INSTALL) $(TARGETS) $(DIST)/bin
|
||||
endif
|
||||
|
||||
symbols::
|
||||
@echo "TARGETS = $(TARGETS)"
|
||||
@@ -1,44 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
|
||||
# do these once for each target program
|
||||
all default export libs program install release_export::
|
||||
$(MAKE) -f make.client $@
|
||||
$(MAKE) -f make.server $@
|
||||
|
||||
# only do these things once for the whole directory
|
||||
depend dependclean clean clobber realclean clobber_all release_classes release_clean release_cpdistdir release_export release_jars release_md release_policy show::
|
||||
$(MAKE) -f make.client $@
|
||||
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
|
||||
ARCH := $(shell uname)
|
||||
|
||||
ifeq ($(ARCH), SunOS)
|
||||
DEFINES = -KPIC -DSVR4 -DSOLARIS -DSYSV -D__svr4 -D__svr4__ \
|
||||
-D_REENTRANT -DSOLARIS2_5 -D_SVID_GETTOD -DXP_UNIX -UDEBUG -DNDEBUG \
|
||||
-DXP_UNIX
|
||||
INCPATH = -I. -I../include/dbm -I../include/nspr -I../include/security
|
||||
LIBPATH = -L../lib
|
||||
LIBS = -lnss -lssl -lpkcs7 -lpkcs12 -lsecmod -lcert -lkey \
|
||||
-lcrypto -lsecutil -lhash -ldbm -lplc4 -lplds4 -lnspr4 -lsocket -lnsl
|
||||
CFLAGS = -g
|
||||
CC = cc
|
||||
endif # SunOS
|
||||
|
||||
# The rules to build the sample apps appear below.
|
||||
|
||||
server:
|
||||
$(CC) $(CFLAGS) $@.c -o $@ $(DEFINES) $(INCPATH) $(LIBPATH) $(LIBS)
|
||||
|
||||
client:
|
||||
$(CC) $(CFLAGS) $@.c -o $@ $(DEFINES) $(INCPATH) $(LIBPATH) $(LIBS)
|
||||
|
||||
clean:
|
||||
rm -fr server client server.o client.o
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
/* General NSPR 2.0 errors */
|
||||
/* Caller must #include "prerror.h" */
|
||||
|
||||
ER2( PR_OUT_OF_MEMORY_ERROR, "Memory allocation attempt failed." )
|
||||
ER2( PR_BAD_DESCRIPTOR_ERROR, "Invalid file descriptor." )
|
||||
ER2( PR_WOULD_BLOCK_ERROR, "The operation would have blocked." )
|
||||
ER2( PR_ACCESS_FAULT_ERROR, "Invalid memory address argument." )
|
||||
ER2( PR_INVALID_METHOD_ERROR, "Invalid function for file type." )
|
||||
ER2( PR_ILLEGAL_ACCESS_ERROR, "Invalid memory address argument." )
|
||||
ER2( PR_UNKNOWN_ERROR, "Some unknown error has occurred." )
|
||||
ER2( PR_PENDING_INTERRUPT_ERROR,"Operation interrupted by another thread." )
|
||||
ER2( PR_NOT_IMPLEMENTED_ERROR, "function not implemented." )
|
||||
ER2( PR_IO_ERROR, "I/O function error." )
|
||||
ER2( PR_IO_TIMEOUT_ERROR, "I/O operation timed out." )
|
||||
ER2( PR_IO_PENDING_ERROR, "I/O operation on busy file descriptor." )
|
||||
ER2( PR_DIRECTORY_OPEN_ERROR, "The directory could not be opened." )
|
||||
ER2( PR_INVALID_ARGUMENT_ERROR, "Invalid function argument." )
|
||||
ER2( PR_ADDRESS_NOT_AVAILABLE_ERROR, "Network address not available (in use?)." )
|
||||
ER2( PR_ADDRESS_NOT_SUPPORTED_ERROR, "Network address type not supported." )
|
||||
ER2( PR_IS_CONNECTED_ERROR, "Already connected." )
|
||||
ER2( PR_BAD_ADDRESS_ERROR, "Network address is invalid." )
|
||||
ER2( PR_ADDRESS_IN_USE_ERROR, "Local Network address is in use." )
|
||||
ER2( PR_CONNECT_REFUSED_ERROR, "Connection refused by peer." )
|
||||
ER2( PR_NETWORK_UNREACHABLE_ERROR, "Network address is presently unreachable." )
|
||||
ER2( PR_CONNECT_TIMEOUT_ERROR, "Connection attempt timed out." )
|
||||
ER2( PR_NOT_CONNECTED_ERROR, "Network file descriptor is not connected." )
|
||||
ER2( PR_LOAD_LIBRARY_ERROR, "Failure to load dynamic library." )
|
||||
ER2( PR_UNLOAD_LIBRARY_ERROR, "Failure to unload dynamic library." )
|
||||
ER2( PR_FIND_SYMBOL_ERROR,
|
||||
"Symbol not found in any of the loaded dynamic libraries." )
|
||||
ER2( PR_INSUFFICIENT_RESOURCES_ERROR, "Insufficient system resources." )
|
||||
ER2( PR_DIRECTORY_LOOKUP_ERROR,
|
||||
"A directory lookup on a network address has failed." )
|
||||
ER2( PR_TPD_RANGE_ERROR,
|
||||
"Attempt to access a TPD key that is out of range." )
|
||||
ER2( PR_PROC_DESC_TABLE_FULL_ERROR, "Process open FD table is full." )
|
||||
ER2( PR_SYS_DESC_TABLE_FULL_ERROR, "System open FD table is full." )
|
||||
ER2( PR_NOT_SOCKET_ERROR,
|
||||
"Network operation attempted on non-network file descriptor." )
|
||||
ER2( PR_NOT_TCP_SOCKET_ERROR,
|
||||
"TCP-specific function attempted on a non-TCP file descriptor." )
|
||||
ER2( PR_SOCKET_ADDRESS_IS_BOUND_ERROR, "TCP file descriptor is already bound." )
|
||||
ER2( PR_NO_ACCESS_RIGHTS_ERROR, "Access Denied." )
|
||||
ER2( PR_OPERATION_NOT_SUPPORTED_ERROR,
|
||||
"The requested operation is not supported by the platform." )
|
||||
ER2( PR_PROTOCOL_NOT_SUPPORTED_ERROR,
|
||||
"The host operating system does not support the protocol requested." )
|
||||
ER2( PR_REMOTE_FILE_ERROR, "Access to the remote file has been severed." )
|
||||
ER2( PR_BUFFER_OVERFLOW_ERROR,
|
||||
"The value requested is too large to be stored in the data buffer provided." )
|
||||
ER2( PR_CONNECT_RESET_ERROR, "TCP connection reset by peer." )
|
||||
ER2( PR_RANGE_ERROR, "Unused." )
|
||||
ER2( PR_DEADLOCK_ERROR, "The operation would have deadlocked." )
|
||||
ER2( PR_FILE_IS_LOCKED_ERROR, "The file is already locked." )
|
||||
ER2( PR_FILE_TOO_BIG_ERROR,
|
||||
"Write would result in file larger than the system allows." )
|
||||
ER2( PR_NO_DEVICE_SPACE_ERROR, "The device for storing the file is full." )
|
||||
ER2( PR_PIPE_ERROR, "Unused." )
|
||||
ER2( PR_NO_SEEK_DEVICE_ERROR, "Unused." )
|
||||
ER2( PR_IS_DIRECTORY_ERROR,
|
||||
"Cannot perform a normal file operation on a directory." )
|
||||
ER2( PR_LOOP_ERROR, "Symbolic link loop." )
|
||||
ER2( PR_NAME_TOO_LONG_ERROR, "File name is too long." )
|
||||
ER2( PR_FILE_NOT_FOUND_ERROR, "File not found." )
|
||||
ER2( PR_NOT_DIRECTORY_ERROR,
|
||||
"Cannot perform directory operation on a normal file." )
|
||||
ER2( PR_READ_ONLY_FILESYSTEM_ERROR,
|
||||
"Cannot write to a read-only file system." )
|
||||
ER2( PR_DIRECTORY_NOT_EMPTY_ERROR,
|
||||
"Cannot delete a directory that is not empty." )
|
||||
ER2( PR_FILESYSTEM_MOUNTED_ERROR,
|
||||
"Cannot delete or rename a file object while the file system is busy." )
|
||||
ER2( PR_NOT_SAME_DEVICE_ERROR,
|
||||
"Cannot rename a file to a file system on another device." )
|
||||
ER2( PR_DIRECTORY_CORRUPTED_ERROR,
|
||||
"The directory object in the file system is corrupted." )
|
||||
ER2( PR_FILE_EXISTS_ERROR,
|
||||
"Cannot create or rename a filename that already exists." )
|
||||
ER2( PR_MAX_DIRECTORY_ENTRIES_ERROR,
|
||||
"Directory is full. No additional filenames may be added." )
|
||||
ER2( PR_INVALID_DEVICE_STATE_ERROR,
|
||||
"The required device was in an invalid state." )
|
||||
ER2( PR_DEVICE_IS_LOCKED_ERROR, "The device is locked." )
|
||||
ER2( PR_NO_MORE_FILES_ERROR, "No more entries in the directory." )
|
||||
ER2( PR_END_OF_FILE_ERROR, "Encountered end of file." )
|
||||
ER2( PR_FILE_SEEK_ERROR, "Seek error." )
|
||||
ER2( PR_FILE_IS_BUSY_ERROR, "The file is busy." )
|
||||
ER2( PR_IN_PROGRESS_ERROR,
|
||||
"Operation is still in progress (probably a non-blocking connect)." )
|
||||
ER2( PR_ALREADY_INITIATED_ERROR,
|
||||
"Operation has already been initiated (probably a non-blocking connect)." )
|
||||
|
||||
#ifdef PR_GROUP_EMPTY_ERROR
|
||||
ER2( PR_GROUP_EMPTY_ERROR, "The wait group is empty." )
|
||||
#endif
|
||||
|
||||
#ifdef PR_INVALID_STATE_ERROR
|
||||
ER2( PR_INVALID_STATE_ERROR, "Object state improper for request." )
|
||||
#endif
|
||||
|
||||
ER2( PR_MAX_ERROR, "Placeholder for the end of the list" )
|
||||
@@ -1,43 +0,0 @@
|
||||
These sample programs can be built in either of two ways:
|
||||
1) is the NSS source tree, using the coreconf build system, and
|
||||
2) stand alone (as part of the NSS distribution).
|
||||
|
||||
The following makefiles are used only when building in the NSS source tree
|
||||
using coreconf. These are NOT part of the distribution.
|
||||
|
||||
Makefile
|
||||
client.mn
|
||||
server.mn
|
||||
config.mk
|
||||
make.client
|
||||
make.server
|
||||
|
||||
The following makefiles are used only when building in the NSS distribution.
|
||||
These files are part of the distribution.
|
||||
|
||||
Makefile.NSS
|
||||
nmakefile95.nss
|
||||
nmakefilent.nss
|
||||
|
||||
|
||||
The following source files are common to both build environments and are
|
||||
part of the distribution.
|
||||
|
||||
NSPRerrs.h
|
||||
SECerrs.h
|
||||
SSLerrs.h
|
||||
client.c
|
||||
getopt.c
|
||||
server.c
|
||||
sslerror.h
|
||||
|
||||
In the NSS 2.0 distribution, the sample code and makefiles are in a
|
||||
directory named "samples". The directories relevant to building
|
||||
in the distributed tree are:
|
||||
|
||||
./samples
|
||||
./include/dbm
|
||||
./include/nspr
|
||||
./include/security
|
||||
./lib
|
||||
|
||||
@@ -1,441 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
/* General security error codes */
|
||||
/* Caller must #include "secerr.h" */
|
||||
|
||||
ER3(SEC_ERROR_IO, SEC_ERROR_BASE + 0,
|
||||
"An I/O error occurred during security authorization.")
|
||||
|
||||
ER3(SEC_ERROR_LIBRARY_FAILURE, SEC_ERROR_BASE + 1,
|
||||
"security library failure.")
|
||||
|
||||
ER3(SEC_ERROR_BAD_DATA, SEC_ERROR_BASE + 2,
|
||||
"security library: received bad data.")
|
||||
|
||||
ER3(SEC_ERROR_OUTPUT_LEN, SEC_ERROR_BASE + 3,
|
||||
"security library: output length error.")
|
||||
|
||||
ER3(SEC_ERROR_INPUT_LEN, SEC_ERROR_BASE + 4,
|
||||
"security library has experienced an input length error.")
|
||||
|
||||
ER3(SEC_ERROR_INVALID_ARGS, SEC_ERROR_BASE + 5,
|
||||
"security library: invalid arguments.")
|
||||
|
||||
ER3(SEC_ERROR_INVALID_ALGORITHM, SEC_ERROR_BASE + 6,
|
||||
"security library: invalid algorithm.")
|
||||
|
||||
ER3(SEC_ERROR_INVALID_AVA, SEC_ERROR_BASE + 7,
|
||||
"security library: invalid AVA.")
|
||||
|
||||
ER3(SEC_ERROR_INVALID_TIME, SEC_ERROR_BASE + 8,
|
||||
"Improperly formatted time string.")
|
||||
|
||||
ER3(SEC_ERROR_BAD_DER, SEC_ERROR_BASE + 9,
|
||||
"security library: improperly formatted DER-encoded message.")
|
||||
|
||||
ER3(SEC_ERROR_BAD_SIGNATURE, SEC_ERROR_BASE + 10,
|
||||
"Peer's certificate has an invalid signature.")
|
||||
|
||||
ER3(SEC_ERROR_EXPIRED_CERTIFICATE, SEC_ERROR_BASE + 11,
|
||||
"Peer's Certificate has expired.")
|
||||
|
||||
ER3(SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_BASE + 12,
|
||||
"Peer's Certificate has been revoked.")
|
||||
|
||||
ER3(SEC_ERROR_UNKNOWN_ISSUER, SEC_ERROR_BASE + 13,
|
||||
"Peer's Certificate issuer is not recognized.")
|
||||
|
||||
ER3(SEC_ERROR_BAD_KEY, SEC_ERROR_BASE + 14,
|
||||
"Peer's public key is invalid.")
|
||||
|
||||
ER3(SEC_ERROR_BAD_PASSWORD, SEC_ERROR_BASE + 15,
|
||||
"The security password entered is incorrect.")
|
||||
|
||||
ER3(SEC_ERROR_RETRY_PASSWORD, SEC_ERROR_BASE + 16,
|
||||
"New password entered incorrectly. Please try again.")
|
||||
|
||||
ER3(SEC_ERROR_NO_NODELOCK, SEC_ERROR_BASE + 17,
|
||||
"security library: no nodelock.")
|
||||
|
||||
ER3(SEC_ERROR_BAD_DATABASE, SEC_ERROR_BASE + 18,
|
||||
"security library: bad database.")
|
||||
|
||||
ER3(SEC_ERROR_NO_MEMORY, SEC_ERROR_BASE + 19,
|
||||
"security library: memory allocation failure.")
|
||||
|
||||
ER3(SEC_ERROR_UNTRUSTED_ISSUER, SEC_ERROR_BASE + 20,
|
||||
"Peer's certificate issuer has been marked as not trusted by the user.")
|
||||
|
||||
ER3(SEC_ERROR_UNTRUSTED_CERT, SEC_ERROR_BASE + 21,
|
||||
"Peer's certificate has been marked as not trusted by the user.")
|
||||
|
||||
ER3(SEC_ERROR_DUPLICATE_CERT, (SEC_ERROR_BASE + 22),
|
||||
"Certificate already exists in your database.")
|
||||
|
||||
ER3(SEC_ERROR_DUPLICATE_CERT_NAME, (SEC_ERROR_BASE + 23),
|
||||
"Downloaded certificate's name duplicates one already in your database.")
|
||||
|
||||
ER3(SEC_ERROR_ADDING_CERT, (SEC_ERROR_BASE + 24),
|
||||
"Error adding certificate to database.")
|
||||
|
||||
ER3(SEC_ERROR_FILING_KEY, (SEC_ERROR_BASE + 25),
|
||||
"Error refiling the key for this certificate.")
|
||||
|
||||
ER3(SEC_ERROR_NO_KEY, (SEC_ERROR_BASE + 26),
|
||||
"The private key for this certificate cannot be found in key database")
|
||||
|
||||
ER3(SEC_ERROR_CERT_VALID, (SEC_ERROR_BASE + 27),
|
||||
"This certificate is valid.")
|
||||
|
||||
ER3(SEC_ERROR_CERT_NOT_VALID, (SEC_ERROR_BASE + 28),
|
||||
"This certificate is not valid.")
|
||||
|
||||
ER3(SEC_ERROR_CERT_NO_RESPONSE, (SEC_ERROR_BASE + 29),
|
||||
"Cert Library: No Response")
|
||||
|
||||
ER3(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE, (SEC_ERROR_BASE + 30),
|
||||
"The certificate issuer's certificate has expired. Check your system date and time.")
|
||||
|
||||
ER3(SEC_ERROR_CRL_EXPIRED, (SEC_ERROR_BASE + 31),
|
||||
"The CRL for the certificate's issuer has expired. Update it or check your system data and time.")
|
||||
|
||||
ER3(SEC_ERROR_CRL_BAD_SIGNATURE, (SEC_ERROR_BASE + 32),
|
||||
"The CRL for the certificate's issuer has an invalid signature.")
|
||||
|
||||
ER3(SEC_ERROR_CRL_INVALID, (SEC_ERROR_BASE + 33),
|
||||
"New CRL has an invalid format.")
|
||||
|
||||
ER3(SEC_ERROR_EXTENSION_VALUE_INVALID, (SEC_ERROR_BASE + 34),
|
||||
"Certificate extension value is invalid.")
|
||||
|
||||
ER3(SEC_ERROR_EXTENSION_NOT_FOUND, (SEC_ERROR_BASE + 35),
|
||||
"Certificate extension not found.")
|
||||
|
||||
ER3(SEC_ERROR_CA_CERT_INVALID, (SEC_ERROR_BASE + 36),
|
||||
"Issuer certificate is invalid.")
|
||||
|
||||
ER3(SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID, (SEC_ERROR_BASE + 37),
|
||||
"Certificate path length constraint is invalid.")
|
||||
|
||||
ER3(SEC_ERROR_CERT_USAGES_INVALID, (SEC_ERROR_BASE + 38),
|
||||
"Certificate usages field is invalid.")
|
||||
|
||||
ER3(SEC_INTERNAL_ONLY, (SEC_ERROR_BASE + 39),
|
||||
"**Internal ONLY module**")
|
||||
|
||||
ER3(SEC_ERROR_INVALID_KEY, (SEC_ERROR_BASE + 40),
|
||||
"The key does not support the requested operation.")
|
||||
|
||||
ER3(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION, (SEC_ERROR_BASE + 41),
|
||||
"Certificate contains unknown critical extension.")
|
||||
|
||||
ER3(SEC_ERROR_OLD_CRL, (SEC_ERROR_BASE + 42),
|
||||
"New CRL is not later than the current one.")
|
||||
|
||||
ER3(SEC_ERROR_NO_EMAIL_CERT, (SEC_ERROR_BASE + 43),
|
||||
"Not encrypted or signed: you do not yet have an email certificate.")
|
||||
|
||||
ER3(SEC_ERROR_NO_RECIPIENT_CERTS_QUERY, (SEC_ERROR_BASE + 44),
|
||||
"Not encrypted: you do not have certificates for each of the recipients.")
|
||||
|
||||
ER3(SEC_ERROR_NOT_A_RECIPIENT, (SEC_ERROR_BASE + 45),
|
||||
"Cannot decrypt: you are not a recipient, or matching certificate and \
|
||||
private key not found.")
|
||||
|
||||
ER3(SEC_ERROR_PKCS7_KEYALG_MISMATCH, (SEC_ERROR_BASE + 46),
|
||||
"Cannot decrypt: key encryption algorithm does not match your certificate.")
|
||||
|
||||
ER3(SEC_ERROR_PKCS7_BAD_SIGNATURE, (SEC_ERROR_BASE + 47),
|
||||
"Signature verification failed: no signer found, too many signers found, \
|
||||
or improper or corrupted data.")
|
||||
|
||||
ER3(SEC_ERROR_UNSUPPORTED_KEYALG, (SEC_ERROR_BASE + 48),
|
||||
"Unsupported or unknown key algorithm.")
|
||||
|
||||
ER3(SEC_ERROR_DECRYPTION_DISALLOWED, (SEC_ERROR_BASE + 49),
|
||||
"Cannot decrypt: encrypted using a disallowed algorithm or key size.")
|
||||
|
||||
|
||||
/* Fortezza Alerts */
|
||||
ER3(XP_SEC_FORTEZZA_BAD_CARD, (SEC_ERROR_BASE + 50),
|
||||
"Fortezza card has not been properly initialized. \
|
||||
Please remove it and return it to your issuer.")
|
||||
|
||||
ER3(XP_SEC_FORTEZZA_NO_CARD, (SEC_ERROR_BASE + 51),
|
||||
"No Fortezza cards Found")
|
||||
|
||||
ER3(XP_SEC_FORTEZZA_NONE_SELECTED, (SEC_ERROR_BASE + 52),
|
||||
"No Fortezza card selected")
|
||||
|
||||
ER3(XP_SEC_FORTEZZA_MORE_INFO, (SEC_ERROR_BASE + 53),
|
||||
"Please select a personality to get more info on")
|
||||
|
||||
ER3(XP_SEC_FORTEZZA_PERSON_NOT_FOUND, (SEC_ERROR_BASE + 54),
|
||||
"Personality not found")
|
||||
|
||||
ER3(XP_SEC_FORTEZZA_NO_MORE_INFO, (SEC_ERROR_BASE + 55),
|
||||
"No more information on that Personality")
|
||||
|
||||
ER3(XP_SEC_FORTEZZA_BAD_PIN, (SEC_ERROR_BASE + 56),
|
||||
"Invalid Pin")
|
||||
|
||||
ER3(XP_SEC_FORTEZZA_PERSON_ERROR, (SEC_ERROR_BASE + 57),
|
||||
"Couldn't initialize Fortezza personalities.")
|
||||
/* end fortezza alerts. */
|
||||
|
||||
ER3(SEC_ERROR_NO_KRL, (SEC_ERROR_BASE + 58),
|
||||
"No KRL for this site's certificate has been found.")
|
||||
|
||||
ER3(SEC_ERROR_KRL_EXPIRED, (SEC_ERROR_BASE + 59),
|
||||
"The KRL for this site's certificate has expired.")
|
||||
|
||||
ER3(SEC_ERROR_KRL_BAD_SIGNATURE, (SEC_ERROR_BASE + 60),
|
||||
"The KRL for this site's certificate has an invalid signature.")
|
||||
|
||||
ER3(SEC_ERROR_REVOKED_KEY, (SEC_ERROR_BASE + 61),
|
||||
"The key for this site's certificate has been revoked.")
|
||||
|
||||
ER3(SEC_ERROR_KRL_INVALID, (SEC_ERROR_BASE + 62),
|
||||
"New KRL has an invalid format.")
|
||||
|
||||
ER3(SEC_ERROR_NEED_RANDOM, (SEC_ERROR_BASE + 63),
|
||||
"security library: need random data.")
|
||||
|
||||
ER3(SEC_ERROR_NO_MODULE, (SEC_ERROR_BASE + 64),
|
||||
"security library: no security module can perform the requested operation.")
|
||||
|
||||
ER3(SEC_ERROR_NO_TOKEN, (SEC_ERROR_BASE + 65),
|
||||
"The security card or token does not exist, needs to be initialized, or has been removed.")
|
||||
|
||||
ER3(SEC_ERROR_READ_ONLY, (SEC_ERROR_BASE + 66),
|
||||
"security library: read-only database.")
|
||||
|
||||
ER3(SEC_ERROR_NO_SLOT_SELECTED, (SEC_ERROR_BASE + 67),
|
||||
"No slot or token was selected.")
|
||||
|
||||
ER3(SEC_ERROR_CERT_NICKNAME_COLLISION, (SEC_ERROR_BASE + 68),
|
||||
"A certificate with the same nickname already exists.")
|
||||
|
||||
ER3(SEC_ERROR_KEY_NICKNAME_COLLISION, (SEC_ERROR_BASE + 69),
|
||||
"A key with the same nickname already exists.")
|
||||
|
||||
ER3(SEC_ERROR_SAFE_NOT_CREATED, (SEC_ERROR_BASE + 70),
|
||||
"error while creating safe object")
|
||||
|
||||
ER3(SEC_ERROR_BAGGAGE_NOT_CREATED, (SEC_ERROR_BASE + 71),
|
||||
"error while creating baggage object")
|
||||
|
||||
ER3(XP_JAVA_REMOVE_PRINCIPAL_ERROR, (SEC_ERROR_BASE + 72),
|
||||
"Couldn't remove the principal")
|
||||
|
||||
ER3(XP_JAVA_DELETE_PRIVILEGE_ERROR, (SEC_ERROR_BASE + 73),
|
||||
"Couldn't delete the privilege")
|
||||
|
||||
ER3(XP_JAVA_CERT_NOT_EXISTS_ERROR, (SEC_ERROR_BASE + 74),
|
||||
"This principal doesn't have a certificate")
|
||||
|
||||
ER3(SEC_ERROR_BAD_EXPORT_ALGORITHM, (SEC_ERROR_BASE + 75),
|
||||
"Required algorithm is not allowed.")
|
||||
|
||||
ER3(SEC_ERROR_EXPORTING_CERTIFICATES, (SEC_ERROR_BASE + 76),
|
||||
"Error attempting to export certificates.")
|
||||
|
||||
ER3(SEC_ERROR_IMPORTING_CERTIFICATES, (SEC_ERROR_BASE + 77),
|
||||
"Error attempting to import certificates.")
|
||||
|
||||
ER3(SEC_ERROR_PKCS12_DECODING_PFX, (SEC_ERROR_BASE + 78),
|
||||
"Unable to import. Decoding error. File not valid.")
|
||||
|
||||
ER3(SEC_ERROR_PKCS12_INVALID_MAC, (SEC_ERROR_BASE + 79),
|
||||
"Unable to import. Invalid MAC. Incorrect password or corrupt file.")
|
||||
|
||||
ER3(SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM, (SEC_ERROR_BASE + 80),
|
||||
"Unable to import. MAC algorithm not supported.")
|
||||
|
||||
ER3(SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE,(SEC_ERROR_BASE + 81),
|
||||
"Unable to import. Only password integrity and privacy modes supported.")
|
||||
|
||||
ER3(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE, (SEC_ERROR_BASE + 82),
|
||||
"Unable to import. File structure is corrupt.")
|
||||
|
||||
ER3(SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM, (SEC_ERROR_BASE + 83),
|
||||
"Unable to import. Encryption algorithm not supported.")
|
||||
|
||||
ER3(SEC_ERROR_PKCS12_UNSUPPORTED_VERSION, (SEC_ERROR_BASE + 84),
|
||||
"Unable to import. File version not supported.")
|
||||
|
||||
ER3(SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT,(SEC_ERROR_BASE + 85),
|
||||
"Unable to import. Incorrect privacy password.")
|
||||
|
||||
ER3(SEC_ERROR_PKCS12_CERT_COLLISION, (SEC_ERROR_BASE + 86),
|
||||
"Unable to import. Same nickname already exists in database.")
|
||||
|
||||
ER3(SEC_ERROR_USER_CANCELLED, (SEC_ERROR_BASE + 87),
|
||||
"The user pressed cancel.")
|
||||
|
||||
ER3(SEC_ERROR_PKCS12_DUPLICATE_DATA, (SEC_ERROR_BASE + 88),
|
||||
"Not imported, already in database.")
|
||||
|
||||
ER3(SEC_ERROR_MESSAGE_SEND_ABORTED, (SEC_ERROR_BASE + 89),
|
||||
"Message not sent.")
|
||||
|
||||
ER3(SEC_ERROR_INADEQUATE_KEY_USAGE, (SEC_ERROR_BASE + 90),
|
||||
"Certificate key usage inadequate for attempted operation.")
|
||||
|
||||
ER3(SEC_ERROR_INADEQUATE_CERT_TYPE, (SEC_ERROR_BASE + 91),
|
||||
"Certificate type not approved for application.")
|
||||
|
||||
ER3(SEC_ERROR_CERT_ADDR_MISMATCH, (SEC_ERROR_BASE + 92),
|
||||
"Address in signing certificate does not match address in message headers.")
|
||||
|
||||
ER3(SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY, (SEC_ERROR_BASE + 93),
|
||||
"Unable to import. Error attempting to import private key.")
|
||||
|
||||
ER3(SEC_ERROR_PKCS12_IMPORTING_CERT_CHAIN, (SEC_ERROR_BASE + 94),
|
||||
"Unable to import. Error attempting to import certificate chain.")
|
||||
|
||||
ER3(SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME, (SEC_ERROR_BASE + 95),
|
||||
"Unable to export. Unable to locate certificate or key by nickname.")
|
||||
|
||||
ER3(SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY, (SEC_ERROR_BASE + 96),
|
||||
"Unable to export. Private Key could not be located and exported.")
|
||||
|
||||
ER3(SEC_ERROR_PKCS12_UNABLE_TO_WRITE, (SEC_ERROR_BASE + 97),
|
||||
"Unable to export. Unable to write the export file.")
|
||||
|
||||
ER3(SEC_ERROR_PKCS12_UNABLE_TO_READ, (SEC_ERROR_BASE + 98),
|
||||
"Unable to import. Unable to read the import file.")
|
||||
|
||||
ER3(SEC_ERROR_PKCS12_KEY_DATABASE_NOT_INITIALIZED, (SEC_ERROR_BASE + 99),
|
||||
"Unable to export. Key database corrupt or deleted.")
|
||||
|
||||
ER3(SEC_ERROR_KEYGEN_FAIL, (SEC_ERROR_BASE + 100),
|
||||
"Unable to generate public/private key pair.")
|
||||
|
||||
ER3(SEC_ERROR_INVALID_PASSWORD, (SEC_ERROR_BASE + 101),
|
||||
"Password entered is invalid. Please pick a different one.")
|
||||
|
||||
ER3(SEC_ERROR_RETRY_OLD_PASSWORD, (SEC_ERROR_BASE + 102),
|
||||
"Old password entered incorrectly. Please try again.")
|
||||
|
||||
ER3(SEC_ERROR_BAD_NICKNAME, (SEC_ERROR_BASE + 103),
|
||||
"Certificate nickname already in use.")
|
||||
|
||||
ER3(SEC_ERROR_NOT_FORTEZZA_ISSUER, (SEC_ERROR_BASE + 104),
|
||||
"Peer FORTEZZA chain has a non-FORTEZZA Certificate.")
|
||||
|
||||
/* ER3(SEC_ERROR_UNKNOWN, (SEC_ERROR_BASE + 105), */
|
||||
|
||||
ER3(SEC_ERROR_JS_INVALID_MODULE_NAME, (SEC_ERROR_BASE + 106),
|
||||
"Invalid module name.")
|
||||
|
||||
ER3(SEC_ERROR_JS_INVALID_DLL, (SEC_ERROR_BASE + 107),
|
||||
"Invalid module path/filename")
|
||||
|
||||
ER3(SEC_ERROR_JS_ADD_MOD_FAILURE, (SEC_ERROR_BASE + 108),
|
||||
"Unable to add module")
|
||||
|
||||
ER3(SEC_ERROR_JS_DEL_MOD_FAILURE, (SEC_ERROR_BASE + 109),
|
||||
"Unable to delete module")
|
||||
|
||||
ER3(SEC_ERROR_OLD_KRL, (SEC_ERROR_BASE + 110),
|
||||
"New KRL is not later than the current one.")
|
||||
|
||||
ER3(SEC_ERROR_CKL_CONFLICT, (SEC_ERROR_BASE + 111),
|
||||
"New CKL has different issuer than current CKL. Delete current CKL.")
|
||||
|
||||
ER3(SEC_ERROR_CERT_NOT_IN_NAME_SPACE, (SEC_ERROR_BASE + 112),
|
||||
"The Certifying Authority for this certificate is not permitted to issue a \
|
||||
certificate with this name.")
|
||||
|
||||
ER3(SEC_ERROR_KRL_NOT_YET_VALID, (SEC_ERROR_BASE + 113),
|
||||
"The key revocation list for this certificate is not yet valid.")
|
||||
|
||||
ER3(SEC_ERROR_CRL_NOT_YET_VALID, (SEC_ERROR_BASE + 114),
|
||||
"The certificate revocation list for this certificate is not yet valid.")
|
||||
|
||||
ER3(SEC_ERROR_UNKNOWN_CERT, (SEC_ERROR_BASE + 115),
|
||||
"The requested certificate could not be found.")
|
||||
|
||||
ER3(SEC_ERROR_UNKNOWN_SIGNER, (SEC_ERROR_BASE + 116),
|
||||
"The signer's certificate could not be found.")
|
||||
|
||||
ER3(SEC_ERROR_CERT_BAD_ACCESS_LOCATION, (SEC_ERROR_BASE + 117),
|
||||
"The location for the certificate status server has invalid format.")
|
||||
|
||||
ER3(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE, (SEC_ERROR_BASE + 118),
|
||||
"The OCSP response cannot be fully decoded; it is of an unknown type.")
|
||||
|
||||
ER3(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE, (SEC_ERROR_BASE + 119),
|
||||
"The OCSP server returned unexpected/invalid HTTP data.")
|
||||
|
||||
ER3(SEC_ERROR_OCSP_MALFORMED_REQUEST, (SEC_ERROR_BASE + 120),
|
||||
"The OCSP server found the request to be corrupted or improperly formed.")
|
||||
|
||||
ER3(SEC_ERROR_OCSP_SERVER_ERROR, (SEC_ERROR_BASE + 121),
|
||||
"The OCSP server experienced an internal error.")
|
||||
|
||||
ER3(SEC_ERROR_OCSP_TRY_SERVER_LATER, (SEC_ERROR_BASE + 122),
|
||||
"The OCSP server suggests trying again later.")
|
||||
|
||||
ER3(SEC_ERROR_OCSP_REQUEST_NEEDS_SIG, (SEC_ERROR_BASE + 123),
|
||||
"The OCSP server requires a signature on this request.")
|
||||
|
||||
ER3(SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST, (SEC_ERROR_BASE + 124),
|
||||
"The OCSP server has refused this request as unauthorized.")
|
||||
|
||||
ER3(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS, (SEC_ERROR_BASE + 125),
|
||||
"The OCSP server returned an unrecognizable status.")
|
||||
|
||||
ER3(SEC_ERROR_OCSP_UNKNOWN_CERT, (SEC_ERROR_BASE + 126),
|
||||
"The OCSP server has no status for the certificate.")
|
||||
|
||||
ER3(SEC_ERROR_OCSP_NOT_ENABLED, (SEC_ERROR_BASE + 127),
|
||||
"You must enable OCSP before performing this operation.")
|
||||
|
||||
ER3(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER, (SEC_ERROR_BASE + 128),
|
||||
"You must set the OCSP default responder before performing this operation.")
|
||||
|
||||
ER3(SEC_ERROR_OCSP_MALFORMED_RESPONSE, (SEC_ERROR_BASE + 129),
|
||||
"The response from the OCSP server was corrupted or improperly formed.")
|
||||
|
||||
ER3(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE, (SEC_ERROR_BASE + 130),
|
||||
"The signer of the OCSP response is not authorized to give status for \
|
||||
this certificate.")
|
||||
|
||||
ER3(SEC_ERROR_OCSP_FUTURE_RESPONSE, (SEC_ERROR_BASE + 131),
|
||||
"The OCSP response is not yet valid (contains a date in the future).")
|
||||
|
||||
ER3(SEC_ERROR_OCSP_OLD_RESPONSE, (SEC_ERROR_BASE + 132),
|
||||
"The OCSP response contains out-of-date information.")
|
||||
@@ -1,366 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
/* SSL-specific security error codes */
|
||||
/* caller must include "sslerr.h" */
|
||||
|
||||
ER3(SSL_ERROR_EXPORT_ONLY_SERVER, SSL_ERROR_BASE + 0,
|
||||
"Unable to communicate securely. Peer does not support high-grade encryption.")
|
||||
|
||||
ER3(SSL_ERROR_US_ONLY_SERVER, SSL_ERROR_BASE + 1,
|
||||
"Unable to communicate securely. Peer requires high-grade encryption which is not supported.")
|
||||
|
||||
ER3(SSL_ERROR_NO_CYPHER_OVERLAP, SSL_ERROR_BASE + 2,
|
||||
"Cannot communicate securely with peer: no common encryption algorithm(s).")
|
||||
|
||||
ER3(SSL_ERROR_NO_CERTIFICATE, SSL_ERROR_BASE + 3,
|
||||
"Unable to find the certificate or key necessary for authentication.")
|
||||
|
||||
ER3(SSL_ERROR_BAD_CERTIFICATE, SSL_ERROR_BASE + 4,
|
||||
"Unable to communicate securely with peer: peers's certificate was rejected.")
|
||||
|
||||
/* unused (SSL_ERROR_BASE + 5),*/
|
||||
|
||||
ER3(SSL_ERROR_BAD_CLIENT, SSL_ERROR_BASE + 6,
|
||||
"The server has encountered bad data from the client.")
|
||||
|
||||
ER3(SSL_ERROR_BAD_SERVER, SSL_ERROR_BASE + 7,
|
||||
"The client has encountered bad data from the server.")
|
||||
|
||||
ER3(SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE, SSL_ERROR_BASE + 8,
|
||||
"Unsupported certificate type.")
|
||||
|
||||
ER3(SSL_ERROR_UNSUPPORTED_VERSION, SSL_ERROR_BASE + 9,
|
||||
"Peer using unsupported version of security protocol.")
|
||||
|
||||
/* unused (SSL_ERROR_BASE + 10),*/
|
||||
|
||||
ER3(SSL_ERROR_WRONG_CERTIFICATE, SSL_ERROR_BASE + 11,
|
||||
"Client authentication failed: private key in key database does not match public key in certificate database.")
|
||||
|
||||
ER3(SSL_ERROR_BAD_CERT_DOMAIN, SSL_ERROR_BASE + 12,
|
||||
"Unable to communicate securely with peer: requested domain name does not match the server's certificate.")
|
||||
|
||||
/* SSL_ERROR_POST_WARNING (SSL_ERROR_BASE + 13),
|
||||
defined in sslerr.h
|
||||
*/
|
||||
|
||||
ER3(SSL_ERROR_SSL2_DISABLED, (SSL_ERROR_BASE + 14),
|
||||
"Peer only supports SSL version 2, which is locally disabled.")
|
||||
|
||||
|
||||
ER3(SSL_ERROR_BAD_MAC_READ, (SSL_ERROR_BASE + 15),
|
||||
"SSL received a record with an incorrect Message Authentication Code.")
|
||||
|
||||
ER3(SSL_ERROR_BAD_MAC_ALERT, (SSL_ERROR_BASE + 16),
|
||||
"SSL peer reports incorrect Message Authentication Code.")
|
||||
|
||||
ER3(SSL_ERROR_BAD_CERT_ALERT, (SSL_ERROR_BASE + 17),
|
||||
"SSL peer cannot verify your certificate.")
|
||||
|
||||
ER3(SSL_ERROR_REVOKED_CERT_ALERT, (SSL_ERROR_BASE + 18),
|
||||
"SSL peer rejected your certificate as revoked.")
|
||||
|
||||
ER3(SSL_ERROR_EXPIRED_CERT_ALERT, (SSL_ERROR_BASE + 19),
|
||||
"SSL peer rejected your certificate as expired.")
|
||||
|
||||
ER3(SSL_ERROR_SSL_DISABLED, (SSL_ERROR_BASE + 20),
|
||||
"Cannot connect: SSL is disabled.")
|
||||
|
||||
ER3(SSL_ERROR_FORTEZZA_PQG, (SSL_ERROR_BASE + 21),
|
||||
"Cannot connect: SSL peer is in another FORTEZZA domain.")
|
||||
|
||||
|
||||
ER3(SSL_ERROR_UNKNOWN_CIPHER_SUITE , (SSL_ERROR_BASE + 22),
|
||||
"An unknown SSL cipher suite has been requested.")
|
||||
|
||||
ER3(SSL_ERROR_NO_CIPHERS_SUPPORTED , (SSL_ERROR_BASE + 23),
|
||||
"No cipher suites are present and enabled in this program.")
|
||||
|
||||
ER3(SSL_ERROR_BAD_BLOCK_PADDING , (SSL_ERROR_BASE + 24),
|
||||
"SSL received a record with bad block padding.")
|
||||
|
||||
ER3(SSL_ERROR_RX_RECORD_TOO_LONG , (SSL_ERROR_BASE + 25),
|
||||
"SSL received a record that exceeded the maximum permissible length.")
|
||||
|
||||
ER3(SSL_ERROR_TX_RECORD_TOO_LONG , (SSL_ERROR_BASE + 26),
|
||||
"SSL attempted to send a record that exceeded the maximum permissible length.")
|
||||
|
||||
/*
|
||||
* Received a malformed (too long or short or invalid content) SSL handshake.
|
||||
*/
|
||||
ER3(SSL_ERROR_RX_MALFORMED_HELLO_REQUEST , (SSL_ERROR_BASE + 27),
|
||||
"SSL received a malformed Hello Request handshake message.")
|
||||
|
||||
ER3(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO , (SSL_ERROR_BASE + 28),
|
||||
"SSL received a malformed Client Hello handshake message.")
|
||||
|
||||
ER3(SSL_ERROR_RX_MALFORMED_SERVER_HELLO , (SSL_ERROR_BASE + 29),
|
||||
"SSL received a malformed Server Hello handshake message.")
|
||||
|
||||
ER3(SSL_ERROR_RX_MALFORMED_CERTIFICATE , (SSL_ERROR_BASE + 30),
|
||||
"SSL received a malformed Certificate handshake message.")
|
||||
|
||||
ER3(SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH , (SSL_ERROR_BASE + 31),
|
||||
"SSL received a malformed Server Key Exchange handshake message.")
|
||||
|
||||
ER3(SSL_ERROR_RX_MALFORMED_CERT_REQUEST , (SSL_ERROR_BASE + 32),
|
||||
"SSL received a malformed Certificate Request handshake message.")
|
||||
|
||||
ER3(SSL_ERROR_RX_MALFORMED_HELLO_DONE , (SSL_ERROR_BASE + 33),
|
||||
"SSL received a malformed Server Hello Done handshake message.")
|
||||
|
||||
ER3(SSL_ERROR_RX_MALFORMED_CERT_VERIFY , (SSL_ERROR_BASE + 34),
|
||||
"SSL received a malformed Certificate Verify handshake message.")
|
||||
|
||||
ER3(SSL_ERROR_RX_MALFORMED_CLIENT_KEY_EXCH , (SSL_ERROR_BASE + 35),
|
||||
"SSL received a malformed Client Key Exchange handshake message.")
|
||||
|
||||
ER3(SSL_ERROR_RX_MALFORMED_FINISHED , (SSL_ERROR_BASE + 36),
|
||||
"SSL received a malformed Finished handshake message.")
|
||||
|
||||
/*
|
||||
* Received a malformed (too long or short) SSL record.
|
||||
*/
|
||||
ER3(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER , (SSL_ERROR_BASE + 37),
|
||||
"SSL received a malformed Change Cipher Spec record.")
|
||||
|
||||
ER3(SSL_ERROR_RX_MALFORMED_ALERT , (SSL_ERROR_BASE + 38),
|
||||
"SSL received a malformed Alert record.")
|
||||
|
||||
ER3(SSL_ERROR_RX_MALFORMED_HANDSHAKE , (SSL_ERROR_BASE + 39),
|
||||
"SSL received a malformed Handshake record.")
|
||||
|
||||
ER3(SSL_ERROR_RX_MALFORMED_APPLICATION_DATA , (SSL_ERROR_BASE + 40),
|
||||
"SSL received a malformed Application Data record.")
|
||||
|
||||
/*
|
||||
* Received an SSL handshake that was inappropriate for the state we're in.
|
||||
* E.g. Server received message from server, or wrong state in state machine.
|
||||
*/
|
||||
ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST , (SSL_ERROR_BASE + 41),
|
||||
"SSL received an unexpected Hello Request handshake message.")
|
||||
|
||||
ER3(SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO , (SSL_ERROR_BASE + 42),
|
||||
"SSL received an unexpected Client Hello handshake message.")
|
||||
|
||||
ER3(SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO , (SSL_ERROR_BASE + 43),
|
||||
"SSL received an unexpected Server Hello handshake message.")
|
||||
|
||||
ER3(SSL_ERROR_RX_UNEXPECTED_CERTIFICATE , (SSL_ERROR_BASE + 44),
|
||||
"SSL received an unexpected Certificate handshake message.")
|
||||
|
||||
ER3(SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH , (SSL_ERROR_BASE + 45),
|
||||
"SSL received an unexpected Server Key Exchange handshake message.")
|
||||
|
||||
ER3(SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST , (SSL_ERROR_BASE + 46),
|
||||
"SSL received an unexpected Certificate Request handshake message.")
|
||||
|
||||
ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE , (SSL_ERROR_BASE + 47),
|
||||
"SSL received an unexpected Server Hello Done handshake message.")
|
||||
|
||||
ER3(SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY , (SSL_ERROR_BASE + 48),
|
||||
"SSL received an unexpected Certificate Verify handshake message.")
|
||||
|
||||
ER3(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH , (SSL_ERROR_BASE + 49),
|
||||
"SSL received an unexpected Cllient Key Exchange handshake message.")
|
||||
|
||||
ER3(SSL_ERROR_RX_UNEXPECTED_FINISHED , (SSL_ERROR_BASE + 50),
|
||||
"SSL received an unexpected Finished handshake message.")
|
||||
|
||||
/*
|
||||
* Received an SSL record that was inappropriate for the state we're in.
|
||||
*/
|
||||
ER3(SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER , (SSL_ERROR_BASE + 51),
|
||||
"SSL received an unexpected Change Cipher Spec record.")
|
||||
|
||||
ER3(SSL_ERROR_RX_UNEXPECTED_ALERT , (SSL_ERROR_BASE + 52),
|
||||
"SSL received an unexpected Alert record.")
|
||||
|
||||
ER3(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE , (SSL_ERROR_BASE + 53),
|
||||
"SSL received an unexpected Handshake record.")
|
||||
|
||||
ER3(SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA, (SSL_ERROR_BASE + 54),
|
||||
"SSL received an unexpected Application Data record.")
|
||||
|
||||
/*
|
||||
* Received record/message with unknown discriminant.
|
||||
*/
|
||||
ER3(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE , (SSL_ERROR_BASE + 55),
|
||||
"SSL received a record with an unknown content type.")
|
||||
|
||||
ER3(SSL_ERROR_RX_UNKNOWN_HANDSHAKE , (SSL_ERROR_BASE + 56),
|
||||
"SSL received a handshake message with an unknown message type.")
|
||||
|
||||
ER3(SSL_ERROR_RX_UNKNOWN_ALERT , (SSL_ERROR_BASE + 57),
|
||||
"SSL received an alert record with an unknown alert description.")
|
||||
|
||||
/*
|
||||
* Received an alert reporting what we did wrong. (more alerts above)
|
||||
*/
|
||||
ER3(SSL_ERROR_CLOSE_NOTIFY_ALERT , (SSL_ERROR_BASE + 58),
|
||||
"SSL peer has closed this connection.")
|
||||
|
||||
ER3(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT , (SSL_ERROR_BASE + 59),
|
||||
"SSL peer was not expecting a handshake message it received.")
|
||||
|
||||
ER3(SSL_ERROR_DECOMPRESSION_FAILURE_ALERT , (SSL_ERROR_BASE + 60),
|
||||
"SSL peer was unable to succesfully decompress an SSL record it received.")
|
||||
|
||||
ER3(SSL_ERROR_HANDSHAKE_FAILURE_ALERT , (SSL_ERROR_BASE + 61),
|
||||
"SSL peer was unable to negotiate an acceptable set of security parameters.")
|
||||
|
||||
ER3(SSL_ERROR_ILLEGAL_PARAMETER_ALERT , (SSL_ERROR_BASE + 62),
|
||||
"SSL peer rejected a handshake message for unacceptable content.")
|
||||
|
||||
ER3(SSL_ERROR_UNSUPPORTED_CERT_ALERT , (SSL_ERROR_BASE + 63),
|
||||
"SSL peer does not support certificates of the type it received.")
|
||||
|
||||
ER3(SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT , (SSL_ERROR_BASE + 64),
|
||||
"SSL peer had some unspecified issue with the certificate it received.")
|
||||
|
||||
|
||||
ER3(SSL_ERROR_GENERATE_RANDOM_FAILURE , (SSL_ERROR_BASE + 65),
|
||||
"SSL experienced a failure of its random number generator.")
|
||||
|
||||
ER3(SSL_ERROR_SIGN_HASHES_FAILURE , (SSL_ERROR_BASE + 66),
|
||||
"Unable to digitally sign data required to verify your certificate.")
|
||||
|
||||
ER3(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE , (SSL_ERROR_BASE + 67),
|
||||
"SSL was unable to extract the public key from the peer's certificate.")
|
||||
|
||||
ER3(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE , (SSL_ERROR_BASE + 68),
|
||||
"Unspecified failure while processing SSL Server Key Exchange handshake.")
|
||||
|
||||
ER3(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE , (SSL_ERROR_BASE + 69),
|
||||
"Unspecified failure while processing SSL Client Key Exchange handshake.")
|
||||
|
||||
ER3(SSL_ERROR_ENCRYPTION_FAILURE , (SSL_ERROR_BASE + 70),
|
||||
"Bulk data encryption algorithm failed in selected cipher suite.")
|
||||
|
||||
ER3(SSL_ERROR_DECRYPTION_FAILURE , (SSL_ERROR_BASE + 71),
|
||||
"Bulk data decryption algorithm failed in selected cipher suite.")
|
||||
|
||||
ER3(SSL_ERROR_SOCKET_WRITE_FAILURE , (SSL_ERROR_BASE + 72),
|
||||
"Attempt to write encrypted data to underlying socket failed.")
|
||||
|
||||
ER3(SSL_ERROR_MD5_DIGEST_FAILURE , (SSL_ERROR_BASE + 73),
|
||||
"MD5 digest function failed.")
|
||||
|
||||
ER3(SSL_ERROR_SHA_DIGEST_FAILURE , (SSL_ERROR_BASE + 74),
|
||||
"SHA-1 digest function failed.")
|
||||
|
||||
ER3(SSL_ERROR_MAC_COMPUTATION_FAILURE , (SSL_ERROR_BASE + 75),
|
||||
"MAC computation failed.")
|
||||
|
||||
ER3(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE , (SSL_ERROR_BASE + 76),
|
||||
"Failure to create Symmetric Key context.")
|
||||
|
||||
ER3(SSL_ERROR_SYM_KEY_UNWRAP_FAILURE , (SSL_ERROR_BASE + 77),
|
||||
"Failure to unwrap the Symmetric key in Client Key Exchange message.")
|
||||
|
||||
ER3(SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED , (SSL_ERROR_BASE + 78),
|
||||
"SSL Server attempted to use domestic-grade public key with export cipher suite.")
|
||||
|
||||
ER3(SSL_ERROR_IV_PARAM_FAILURE , (SSL_ERROR_BASE + 79),
|
||||
"PKCS11 code failed to translate an IV into a param.")
|
||||
|
||||
ER3(SSL_ERROR_INIT_CIPHER_SUITE_FAILURE , (SSL_ERROR_BASE + 80),
|
||||
"Failed to initialize the selected cipher suite.")
|
||||
|
||||
ER3(SSL_ERROR_SESSION_KEY_GEN_FAILURE , (SSL_ERROR_BASE + 81),
|
||||
"Client failed to generate session keys for SSL session.")
|
||||
|
||||
ER3(SSL_ERROR_NO_SERVER_KEY_FOR_ALG , (SSL_ERROR_BASE + 82),
|
||||
"Server has no key for the attempted key exchange algorithm.")
|
||||
|
||||
ER3(SSL_ERROR_TOKEN_INSERTION_REMOVAL , (SSL_ERROR_BASE + 83),
|
||||
"PKCS#11 token was inserted or removed while operation was in progress.")
|
||||
|
||||
ER3(SSL_ERROR_TOKEN_SLOT_NOT_FOUND , (SSL_ERROR_BASE + 84),
|
||||
"No PKCS#11 token could be found to do a required operation.")
|
||||
|
||||
ER3(SSL_ERROR_NO_COMPRESSION_OVERLAP , (SSL_ERROR_BASE + 85),
|
||||
"Cannot communicate securely with peer: no common compression algorithm(s).")
|
||||
|
||||
ER3(SSL_ERROR_HANDSHAKE_NOT_COMPLETED , (SSL_ERROR_BASE + 86),
|
||||
"Cannot initiate another SSL handshake until current handshake is complete.")
|
||||
|
||||
ER3(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE , (SSL_ERROR_BASE + 87),
|
||||
"Received incorrect handshakes hash values from peer.")
|
||||
|
||||
ER3(SSL_ERROR_CERT_KEA_MISMATCH , (SSL_ERROR_BASE + 88),
|
||||
"The certificate provided cannot be used with the selected key exchange algorithm.")
|
||||
|
||||
ER3(SSL_ERROR_NO_TRUSTED_SSL_CLIENT_CA , (SSL_ERROR_BASE + 89),
|
||||
"No certificate authority is trusted for SSL client authentication.")
|
||||
|
||||
ER3(SSL_ERROR_SESSION_NOT_FOUND , (SSL_ERROR_BASE + 90),
|
||||
"Client's SSL session ID not found in server's session cache.")
|
||||
|
||||
ER3(SSL_ERROR_DECRYPTION_FAILED_ALERT , (SSL_ERROR_BASE + 91),
|
||||
"Peer was unable to decrypt an SSL record it received.")
|
||||
|
||||
ER3(SSL_ERROR_RECORD_OVERFLOW_ALERT , (SSL_ERROR_BASE + 92),
|
||||
"Peer received an SSL record that was longer than is permitted.")
|
||||
|
||||
ER3(SSL_ERROR_UNKNOWN_CA_ALERT , (SSL_ERROR_BASE + 93),
|
||||
"Peer does not recognize and trust the CA that issued your certificate.")
|
||||
|
||||
ER3(SSL_ERROR_ACCESS_DENIED_ALERT , (SSL_ERROR_BASE + 94),
|
||||
"Peer received a valid certificate, but access was denied.")
|
||||
|
||||
ER3(SSL_ERROR_DECODE_ERROR_ALERT , (SSL_ERROR_BASE + 95),
|
||||
"Peer could not decode an SSL handshake message.")
|
||||
|
||||
ER3(SSL_ERROR_DECRYPT_ERROR_ALERT , (SSL_ERROR_BASE + 96),
|
||||
"Peer reports failure of signature verification or key exchange.")
|
||||
|
||||
ER3(SSL_ERROR_EXPORT_RESTRICTION_ALERT , (SSL_ERROR_BASE + 97),
|
||||
"Peer reports negotiation not in compliance with export regulations.")
|
||||
|
||||
ER3(SSL_ERROR_PROTOCOL_VERSION_ALERT , (SSL_ERROR_BASE + 98),
|
||||
"Peer reports incompatible or unsupported protocol version.")
|
||||
|
||||
ER3(SSL_ERROR_INSUFFICIENT_SECURITY_ALERT , (SSL_ERROR_BASE + 99),
|
||||
"Server requires ciphers more secure than those supported by client.")
|
||||
|
||||
ER3(SSL_ERROR_INTERNAL_ERROR_ALERT , (SSL_ERROR_BASE + 100),
|
||||
"Peer reports it experienced an internal error.")
|
||||
|
||||
ER3(SSL_ERROR_USER_CANCELED_ALERT , (SSL_ERROR_BASE + 101),
|
||||
"Peer user canceled handshake.")
|
||||
|
||||
ER3(SSL_ERROR_NO_RENEGOTIATION_ALERT , (SSL_ERROR_BASE + 102),
|
||||
"Peer does not permit renegotiation of SSL security parameters.")
|
||||
|
||||
@@ -1,451 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* SSL client program that sets up a connection to SSL server, transmits *
|
||||
* some data and then reads the reply *
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(XP_UNIX)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "prerror.h"
|
||||
|
||||
#include "pk11func.h"
|
||||
#include "secitem.h"
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "nspr.h"
|
||||
#include "plgetopt.h"
|
||||
#include "prio.h"
|
||||
#include "prnetdb.h"
|
||||
#include "nss.h"
|
||||
|
||||
#include "sslsample.h"
|
||||
|
||||
#define RD_BUF_SIZE (60 * 1024)
|
||||
|
||||
extern int ssl2CipherSuites[];
|
||||
extern int ssl3CipherSuites[];
|
||||
|
||||
GlobalThreadMgr threadMGR;
|
||||
char *certNickname = NULL;
|
||||
char *hostName = NULL;
|
||||
char *password = NULL;
|
||||
unsigned short port = 0;
|
||||
|
||||
static void
|
||||
Usage(const char *progName)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: %s [-n rsa_nickname] [-p port] [-d dbdir] [-c connections]\n"
|
||||
" [-w dbpasswd] [-C cipher(s)] hostname\n",
|
||||
progName);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
PRFileDesc *
|
||||
setupSSLSocket(PRNetAddr *addr)
|
||||
{
|
||||
PRFileDesc *tcpSocket;
|
||||
PRFileDesc *sslSocket;
|
||||
PRSocketOptionData socketOption;
|
||||
PRStatus prStatus;
|
||||
SECStatus secStatus;
|
||||
|
||||
#if 0
|
||||
retry:
|
||||
#endif
|
||||
|
||||
tcpSocket = PR_NewTCPSocket();
|
||||
if (tcpSocket == NULL) {
|
||||
errWarn("PR_NewTCPSocket");
|
||||
}
|
||||
|
||||
/* Make the socket blocking. */
|
||||
socketOption.option = PR_SockOpt_Nonblocking;
|
||||
socketOption.value.non_blocking = PR_FALSE;
|
||||
|
||||
prStatus = PR_SetSocketOption(tcpSocket, &socketOption);
|
||||
if (prStatus != PR_SUCCESS) {
|
||||
errWarn("PR_SetSocketOption");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Verify that a connection can be made to the socket. */
|
||||
prStatus = PR_Connect(tcpSocket, addr, PR_INTERVAL_NO_TIMEOUT);
|
||||
if (prStatus != PR_SUCCESS) {
|
||||
PRErrorCode err = PR_GetError();
|
||||
if (err == PR_CONNECT_REFUSED_ERROR) {
|
||||
PR_Close(tcpSocket);
|
||||
PR_Sleep(PR_MillisecondsToInterval(10));
|
||||
fprintf(stderr, "Connection to port refused, retrying.\n");
|
||||
goto retry;
|
||||
}
|
||||
errWarn("PR_Connect");
|
||||
goto loser;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Import the socket into the SSL layer. */
|
||||
sslSocket = SSL_ImportFD(NULL, tcpSocket);
|
||||
if (!sslSocket) {
|
||||
errWarn("SSL_ImportFD");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* Set configuration options. */
|
||||
secStatus = SSL_OptionSet(sslSocket, SSL_SECURITY, PR_TRUE);
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_OptionSet:SSL_SECURITY");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
secStatus = SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_OptionSet:SSL_HANDSHAKE_AS_CLIENT");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* Set SSL callback routines. */
|
||||
secStatus = SSL_GetClientAuthDataHook(sslSocket,
|
||||
(SSLGetClientAuthData)myGetClientAuthData,
|
||||
(void *)certNickname);
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_GetClientAuthDataHook");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
secStatus = SSL_AuthCertificateHook(sslSocket,
|
||||
(SSLAuthCertificate)myAuthCertificate,
|
||||
(void *)CERT_GetDefaultCertDB());
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_AuthCertificateHook");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
secStatus = SSL_BadCertHook(sslSocket,
|
||||
(SSLBadCertHandler)myBadCertHandler, NULL);
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_BadCertHook");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
secStatus = SSL_HandshakeCallback(sslSocket,
|
||||
(SSLHandshakeCallback)myHandshakeCallback,
|
||||
NULL);
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_HandshakeCallback");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
return sslSocket;
|
||||
|
||||
loser:
|
||||
|
||||
PR_Close(tcpSocket);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const char requestString[] = {"GET /testfile HTTP/1.0\r\n\r\n" };
|
||||
|
||||
SECStatus
|
||||
handle_connection(PRFileDesc *sslSocket, int connection)
|
||||
{
|
||||
int countRead = 0;
|
||||
PRInt32 numBytes;
|
||||
char *readBuffer;
|
||||
|
||||
readBuffer = PORT_Alloc(RD_BUF_SIZE);
|
||||
if (!readBuffer) {
|
||||
exitErr("PORT_Alloc");
|
||||
}
|
||||
|
||||
/* compose the http request here. */
|
||||
|
||||
numBytes = PR_Write(sslSocket, requestString, strlen(requestString));
|
||||
if (numBytes <= 0) {
|
||||
errWarn("PR_Write");
|
||||
PR_Free(readBuffer);
|
||||
readBuffer = NULL;
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* read until EOF */
|
||||
while (PR_TRUE) {
|
||||
numBytes = PR_Read(sslSocket, readBuffer, RD_BUF_SIZE);
|
||||
if (numBytes == 0) {
|
||||
break; /* EOF */
|
||||
}
|
||||
if (numBytes < 0) {
|
||||
errWarn("PR_Read");
|
||||
break;
|
||||
}
|
||||
countRead += numBytes;
|
||||
fprintf(stderr, "***** Connection %d read %d bytes (%d total).\n",
|
||||
connection, numBytes, countRead );
|
||||
readBuffer[numBytes] = '\0';
|
||||
fprintf(stderr, "************\n%s\n************\n", readBuffer);
|
||||
}
|
||||
|
||||
printSecurityInfo(sslSocket);
|
||||
|
||||
PR_Free(readBuffer);
|
||||
readBuffer = NULL;
|
||||
|
||||
/* Caller closes the socket. */
|
||||
|
||||
fprintf(stderr,
|
||||
"***** Connection %d read %d bytes total.\n",
|
||||
connection, countRead);
|
||||
|
||||
return SECSuccess; /* success */
|
||||
}
|
||||
|
||||
/* one copy of this function is launched in a separate thread for each
|
||||
** connection to be made.
|
||||
*/
|
||||
SECStatus
|
||||
do_connects(void *a, int connection)
|
||||
{
|
||||
PRNetAddr *addr = (PRNetAddr *)a;
|
||||
PRFileDesc *sslSocket;
|
||||
PRHostEnt hostEntry;
|
||||
char buffer[PR_NETDB_BUF_SIZE];
|
||||
PRStatus prStatus;
|
||||
PRIntn hostenum;
|
||||
SECStatus secStatus;
|
||||
|
||||
/* Set up SSL secure socket. */
|
||||
sslSocket = setupSSLSocket(addr);
|
||||
if (sslSocket == NULL) {
|
||||
errWarn("setupSSLSocket");
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
secStatus = SSL_SetPKCS11PinArg(sslSocket, password);
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_SetPKCS11PinArg");
|
||||
return secStatus;
|
||||
}
|
||||
|
||||
secStatus = SSL_SetURL(sslSocket, hostName);
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_SetURL");
|
||||
return secStatus;
|
||||
}
|
||||
|
||||
/* Prepare and setup network connection. */
|
||||
prStatus = PR_GetHostByName(hostName, buffer, sizeof(buffer), &hostEntry);
|
||||
if (prStatus != PR_SUCCESS) {
|
||||
errWarn("PR_GetHostByName");
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
hostenum = PR_EnumerateHostEnt(0, &hostEntry, port, addr);
|
||||
if (hostenum == -1) {
|
||||
errWarn("PR_EnumerateHostEnt");
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
prStatus = PR_Connect(sslSocket, addr, PR_INTERVAL_NO_TIMEOUT);
|
||||
if (prStatus != PR_SUCCESS) {
|
||||
errWarn("PR_Connect");
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Established SSL connection, ready to send data. */
|
||||
#if 0
|
||||
secStatus = SSL_ForceHandshake(sslSocket);
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_ForceHandshake");
|
||||
return secStatus;
|
||||
}
|
||||
#endif
|
||||
|
||||
secStatus = SSL_ResetHandshake(sslSocket, /* asServer */ PR_FALSE);
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_ResetHandshake");
|
||||
prStatus = PR_Close(sslSocket);
|
||||
if (prStatus != PR_SUCCESS) {
|
||||
errWarn("PR_Close");
|
||||
}
|
||||
return secStatus;
|
||||
}
|
||||
|
||||
secStatus = handle_connection(sslSocket, connection);
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("handle_connection");
|
||||
return secStatus;
|
||||
}
|
||||
|
||||
PR_Close(sslSocket);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
void
|
||||
client_main(unsigned short port,
|
||||
int connections,
|
||||
const char * hostName)
|
||||
{
|
||||
int i;
|
||||
SECStatus secStatus;
|
||||
PRStatus prStatus;
|
||||
PRInt32 rv;
|
||||
PRNetAddr addr;
|
||||
PRHostEnt hostEntry;
|
||||
char buffer[256];
|
||||
|
||||
/* Setup network connection. */
|
||||
prStatus = PR_GetHostByName(hostName, buffer, 256, &hostEntry);
|
||||
if (prStatus != PR_SUCCESS) {
|
||||
exitErr("PR_GetHostByName");
|
||||
}
|
||||
|
||||
rv = PR_EnumerateHostEnt(0, &hostEntry, port, &addr);
|
||||
if (rv < 0) {
|
||||
exitErr("PR_EnumerateHostEnt");
|
||||
}
|
||||
|
||||
secStatus = launch_thread(&threadMGR, do_connects, &addr, 1);
|
||||
if (secStatus != SECSuccess) {
|
||||
exitErr("launch_thread");
|
||||
}
|
||||
|
||||
if (connections > 1) {
|
||||
/* wait for the first connection to terminate, then launch the rest. */
|
||||
reap_threads(&threadMGR);
|
||||
/* Start up the connections */
|
||||
for (i = 2; i <= connections; ++i) {
|
||||
secStatus = launch_thread(&threadMGR, do_connects, &addr, i);
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("launch_thread");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reap_threads(&threadMGR);
|
||||
destroy_thread_data(&threadMGR);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char * certDir = ".";
|
||||
char * progName = NULL;
|
||||
int connections = 1;
|
||||
char * cipherString = NULL;
|
||||
SECStatus secStatus;
|
||||
PLOptState * optstate;
|
||||
PLOptStatus status;
|
||||
|
||||
/* Call the NSPR initialization routines */
|
||||
PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
|
||||
|
||||
progName = PL_strdup(argv[0]);
|
||||
|
||||
hostName = NULL;
|
||||
optstate = PL_CreateOptState(argc, argv, "C:c:d:n:p:w:");
|
||||
while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
|
||||
switch(optstate->option) {
|
||||
case 'C' : cipherString = PL_strdup(optstate->value); break;
|
||||
case 'c' : connections = PORT_Atoi(optstate->value); break;
|
||||
case 'd' : certDir = PL_strdup(optstate->value); break;
|
||||
case 'n' : certNickname = PL_strdup(optstate->value); break;
|
||||
case 'p' : port = PORT_Atoi(optstate->value); break;
|
||||
case 'w' : password = PL_strdup(optstate->value); break;
|
||||
case '\0': hostName = PL_strdup(optstate->value); break;
|
||||
default : Usage(progName);
|
||||
}
|
||||
}
|
||||
|
||||
if (port == 0 || hostName == NULL)
|
||||
Usage(progName);
|
||||
|
||||
if (certDir == NULL) {
|
||||
certDir = PR_smprintf("%s/.netscape", getenv("HOME"));
|
||||
}
|
||||
|
||||
/* Set our password function callback. */
|
||||
PK11_SetPasswordFunc(myPasswd);
|
||||
|
||||
/* Initialize the NSS libraries. */
|
||||
secStatus = NSS_Init(certDir);
|
||||
if (secStatus != SECSuccess) {
|
||||
exitErr("NSS_Init");
|
||||
}
|
||||
|
||||
/* All cipher suites except RSA_NULL_MD5 are enabled by Domestic Policy. */
|
||||
NSS_SetDomesticPolicy();
|
||||
SSL_CipherPrefSetDefault(SSL_RSA_WITH_NULL_MD5, PR_TRUE);
|
||||
|
||||
/* all the SSL2 and SSL3 cipher suites are enabled by default. */
|
||||
if (cipherString) {
|
||||
int ndx;
|
||||
|
||||
/* disable all the ciphers, then enable the ones we want. */
|
||||
disableAllSSLCiphers();
|
||||
|
||||
while (0 != (ndx = *cipherString++)) {
|
||||
int *cptr;
|
||||
int cipher;
|
||||
|
||||
if (! isalpha(ndx))
|
||||
Usage(progName);
|
||||
cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites;
|
||||
for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0; )
|
||||
/* do nothing */;
|
||||
if (cipher) {
|
||||
SSL_CipherPrefSetDefault(cipher, PR_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
client_main(port, connections, hostName);
|
||||
|
||||
NSS_Shutdown();
|
||||
PR_Cleanup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
|
||||
CORE_DEPTH = ../../..
|
||||
|
||||
MODULE = security
|
||||
|
||||
EXPORTS =
|
||||
|
||||
CSRCS = client.c \
|
||||
sslsample.c \
|
||||
$(NULL)
|
||||
|
||||
PROGRAM = client
|
||||
|
||||
REQUIRES = dbm
|
||||
|
||||
IMPORTS = security/lib/nss
|
||||
|
||||
DEFINES = -DNSPR20
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
#
|
||||
# Script to generate sample db files neccessary for SSL.
|
||||
|
||||
# Directory for db's, use in all subsequent -d flags.
|
||||
rm -rf SampleCertDBs
|
||||
mkdir SampleCertDBs
|
||||
|
||||
# Password to use.
|
||||
echo sample > passfile
|
||||
|
||||
# Generate the db files, using the above password.
|
||||
certutil -N -d SampleCertDBs -f passfile
|
||||
|
||||
# Generate the CA cert. This cert is self-signed and only useful for
|
||||
# test purposes. Set the trust bits to allow it to sign SSL client/server
|
||||
# certs.
|
||||
certutil -S -n SampleRootCA -x -t "CTu,CTu,CTu" \
|
||||
-s "CN=My Sample Root CA, O=My Organization" \
|
||||
-m 25000 -o ./SampleCertDBs/SampleRootCA.crt \
|
||||
-d SampleCertDBs -f passfile
|
||||
|
||||
# Generate the server cert. This cert is signed by the CA cert generated
|
||||
# above. The CN must be hostname.domain.[com|org|net|...].
|
||||
certutil -S -n SampleSSLServerCert -c SampleRootCA -t "u,u,u" \
|
||||
-s "CN=$HOSTNAME.$MYDOMAIN, O=$HOSTNAME Corp." \
|
||||
-m 25001 -o ./SampleCertDBs/SampleSSLServer.crt \
|
||||
-d SampleCertDBs -f passfile
|
||||
|
||||
# Generate the client cert. This cert is signed by the CA cert generated
|
||||
# above.
|
||||
certutil -S -n SampleSSLClientCert -c SampleRootCA -t "u,u,u" \
|
||||
-s "CN=My Client Cert, O=Client Organization" \
|
||||
-m 25002 -o ./SampleCertDBs/SampleSSLClient.crt \
|
||||
-d SampleCertDBs -f passfile
|
||||
|
||||
# Verify the certificates.
|
||||
certutil -V -u V -n SampleSSLServerCert -d SampleCertDBs
|
||||
certutil -V -u C -n SampleSSLClientCert -d SampleCertDBs
|
||||
|
||||
# Remove unneccessary files.
|
||||
rm -f passfile
|
||||
rm -f tempcert*
|
||||
|
||||
# You are now ready to run your client/server! Example command lines:
|
||||
# server -n SampleSSLServerCert -p 8080 -d SampleCertDBs -w sample -c e -R
|
||||
# client -n SampleSSLClientCert -p 8080 -d SampleCertDBs -w sample -c 2 trane.mcom.com
|
||||
@@ -1,78 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
#
|
||||
|
||||
#######################################################################
|
||||
# (1) Include initial platform-independent assignments (MANDATORY). #
|
||||
#######################################################################
|
||||
|
||||
include client.mn
|
||||
|
||||
#######################################################################
|
||||
# (2) Include "global" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/config.mk
|
||||
|
||||
#######################################################################
|
||||
# (3) Include "component" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
#include $(CORE_DEPTH)/$(MODULE)/config/config.mk
|
||||
|
||||
#######################################################################
|
||||
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
include ../platlibs.mk
|
||||
|
||||
#######################################################################
|
||||
# (5) Execute "global" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/rules.mk
|
||||
|
||||
#######################################################################
|
||||
# (6) Execute "component" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (7) Execute "local" rules. (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
#CC = cc
|
||||
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
#
|
||||
|
||||
#######################################################################
|
||||
# (1) Include initial platform-independent assignments (MANDATORY). #
|
||||
#######################################################################
|
||||
|
||||
include server.mn
|
||||
|
||||
#######################################################################
|
||||
# (2) Include "global" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/config.mk
|
||||
|
||||
#######################################################################
|
||||
# (3) Include "component" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
#include $(CORE_DEPTH)/$(MODULE)/config/config.mk
|
||||
|
||||
#######################################################################
|
||||
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
include ../platlibs.mk
|
||||
|
||||
#######################################################################
|
||||
# (5) Execute "global" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/rules.mk
|
||||
|
||||
#######################################################################
|
||||
# (6) Execute "component" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (7) Execute "local" rules. (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
|
||||
# NSS 2.6.2 Sample Win95 Makefile
|
||||
#
|
||||
#
|
||||
# This nmake file will build server.c and client.c on Windows 95.
|
||||
#
|
||||
|
||||
DEFINES=-D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG -DWIN32 -D_WINDOWS
|
||||
|
||||
INCPATH=/I. /I..\include\dbm /I..\include\nspr /I..\include\security
|
||||
|
||||
LIBS=nss.lib ssl.lib pkcs7.lib pkcs12.lib secmod.lib cert.lib key.lib crypto.lib secutil.lib hash.lib dbm.lib libplc3.lib libplds3.lib libnspr3.lib wsock32.lib
|
||||
|
||||
CFLAGS=-O2 -MD -W3 -nologo
|
||||
|
||||
CC=cl
|
||||
|
||||
LDOPTIONS=/link /LIBPATH:..\lib /nodefaultlib:libcd.lib /subsystem:console
|
||||
|
||||
server:
|
||||
$(CC) $(CFLAGS) $(INCPATH) /Feserver server.c getopt.c $(LIBS) $(DEFINES) $(LDOPTIONS)
|
||||
|
||||
client:
|
||||
$(CC) $(CFLAGS) $(INCPATH) /Feclient client.c getopt.c $(LIBS) $(DEFINES) $(LDOPTIONS)
|
||||
|
||||
clean:
|
||||
del /S server.exe client.exe server.lib server.exp client.lib client.exp server.obj client.obj getopt.obj
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
|
||||
# NSS 2.6.2 Sample NT Makefile
|
||||
#
|
||||
#
|
||||
# This nmake file will build server.c and client.c on Windows NT 4 SP3.
|
||||
#
|
||||
|
||||
DEFINES=-D_X86_ -GT -DWINNT -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG -DWIN32 -D_WINDOWS
|
||||
INCPATH=-I. -I..\include\dbm -I..\include\nspr -I..\include\security
|
||||
|
||||
LIBS=nss.lib ssl.lib pkcs7.lib pkcs12.lib secmod.lib cert.lib key.lib crypto.lib secutil.lib hash.lib dbm.lib libplc3.lib libplds3.lib libnspr3.lib wsock32.lib
|
||||
|
||||
CFLAGS=-O2 -MD -W3 -nologo
|
||||
|
||||
CC=cl
|
||||
|
||||
LDOPTIONS=/link /LIBPATH:..\lib /nodefaultlib:libcd.lib /subsystem:console
|
||||
|
||||
server:
|
||||
$(CC) $(CFLAGS) /Feserver server.c getopt.c $(LIBS) $(DEFINES) $(INCPATH) $(LDOPTIONS)
|
||||
|
||||
client:
|
||||
$(CC) $(CFLAGS) /Feclient client.c getopt.c $(LIBS) $(DEFINES) $(INCPATH) $(LDOPTIONS)
|
||||
|
||||
clean:
|
||||
del /S server.exe client.exe server.lib server.exp client.lib client.exp server.obj client.obj getopt.obj
|
||||
|
||||
@@ -1,820 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* SSL server program listens on a port, accepts client connection, reads *
|
||||
* request and responds to it *
|
||||
****************************************************************************/
|
||||
|
||||
/* Generic header files */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* NSPR header files */
|
||||
|
||||
#include "nspr.h"
|
||||
#include "plgetopt.h"
|
||||
#include "prerror.h"
|
||||
#include "prnetdb.h"
|
||||
|
||||
/* NSS header files */
|
||||
|
||||
#include "pk11func.h"
|
||||
#include "secitem.h"
|
||||
#include "ssl.h"
|
||||
#include "certt.h"
|
||||
#include "nss.h"
|
||||
#include "secrng.h"
|
||||
#include "secder.h"
|
||||
#include "key.h"
|
||||
#include "sslproto.h"
|
||||
|
||||
/* Custom header files */
|
||||
|
||||
#include "sslsample.h"
|
||||
|
||||
#ifndef PORT_Sprintf
|
||||
#define PORT_Sprintf sprintf
|
||||
#endif
|
||||
|
||||
#define REQUEST_CERT_ONCE 1
|
||||
#define REQUIRE_CERT_ONCE 2
|
||||
#define REQUEST_CERT_ALL 3
|
||||
#define REQUIRE_CERT_ALL 4
|
||||
|
||||
/* Global variables */
|
||||
GlobalThreadMgr threadMGR;
|
||||
char *password = NULL;
|
||||
CERTCertificate *cert = NULL;
|
||||
SECKEYPrivateKey *privKey = NULL;
|
||||
int stopping;
|
||||
|
||||
static void
|
||||
Usage(const char *progName)
|
||||
{
|
||||
fprintf(stderr,
|
||||
|
||||
"Usage: %s -n rsa_nickname -p port [-3RFrf] [-w password]\n"
|
||||
" [-c ciphers] [-d dbdir] \n"
|
||||
"-3 means disable SSL v3\n"
|
||||
"-r means request certificate on first handshake.\n"
|
||||
"-f means require certificate on first handshake.\n"
|
||||
"-R means request certificate on all handshakes.\n"
|
||||
"-F means require certificate on all handshakes.\n"
|
||||
"-c ciphers Letter(s) chosen from the following list\n"
|
||||
"A SSL2 RC4 128 WITH MD5\n"
|
||||
"B SSL2 RC4 128 EXPORT40 WITH MD5\n"
|
||||
"C SSL2 RC2 128 CBC WITH MD5\n"
|
||||
"D SSL2 RC2 128 CBC EXPORT40 WITH MD5\n"
|
||||
"E SSL2 DES 64 CBC WITH MD5\n"
|
||||
"F SSL2 DES 192 EDE3 CBC WITH MD5\n"
|
||||
"\n"
|
||||
"a SSL3 FORTEZZA DMS WITH FORTEZZA CBC SHA\n"
|
||||
"b SSL3 FORTEZZA DMS WITH RC4 128 SHA\n"
|
||||
"c SSL3 RSA WITH RC4 128 MD5\n"
|
||||
"d SSL3 RSA WITH 3DES EDE CBC SHA\n"
|
||||
"e SSL3 RSA WITH DES CBC SHA\n"
|
||||
"f SSL3 RSA EXPORT WITH RC4 40 MD5\n"
|
||||
"g SSL3 RSA EXPORT WITH RC2 CBC 40 MD5\n"
|
||||
"h SSL3 FORTEZZA DMS WITH NULL SHA\n"
|
||||
"i SSL3 RSA WITH NULL MD5\n"
|
||||
"j SSL3 RSA FIPS WITH 3DES EDE CBC SHA\n"
|
||||
"k SSL3 RSA FIPS WITH DES CBC SHA\n"
|
||||
"l SSL3 RSA EXPORT WITH DES CBC SHA\t(new)\n"
|
||||
"m SSL3 RSA EXPORT WITH RC4 56 SHA\t(new)\n",
|
||||
progName);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Function: readDataFromSocket()
|
||||
*
|
||||
* Purpose: Parse an HTTP request by reading data from a GET or POST.
|
||||
*
|
||||
*/
|
||||
SECStatus
|
||||
readDataFromSocket(PRFileDesc *sslSocket, DataBuffer *buffer, char **fileName)
|
||||
{
|
||||
char *post;
|
||||
int numBytes = 0;
|
||||
int newln = 0; /* # of consecutive newlns */
|
||||
|
||||
/* Read data while it comes in from the socket. */
|
||||
while (PR_TRUE) {
|
||||
buffer->index = 0;
|
||||
newln = 0;
|
||||
|
||||
/* Read the buffer. */
|
||||
numBytes = PR_Read(sslSocket, &buffer->data[buffer->index],
|
||||
buffer->remaining);
|
||||
if (numBytes <= 0) {
|
||||
errWarn("PR_Read");
|
||||
return SECFailure;
|
||||
}
|
||||
buffer->dataEnd = buffer->dataStart + numBytes;
|
||||
|
||||
/* Parse the input, starting at the beginning of the buffer.
|
||||
* Stop when we detect two consecutive \n's (or \r\n's)
|
||||
* as this signifies the end of the GET or POST portion.
|
||||
* The posted data follows.
|
||||
*/
|
||||
while (buffer->index < buffer->dataEnd && newln < 2) {
|
||||
int octet = buffer->data[buffer->index++];
|
||||
if (octet == '\n') {
|
||||
newln++;
|
||||
} else if (octet != '\r') {
|
||||
newln = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Came to the end of the buffer, or second newline.
|
||||
* If we didn't get an empty line ("\r\n\r\n"), then keep on reading.
|
||||
*/
|
||||
if (newln < 2)
|
||||
continue;
|
||||
|
||||
/* we're at the end of the HTTP request.
|
||||
* If the request is a POST, then there will be one more
|
||||
* line of data.
|
||||
* This parsing is a hack, but ok for SSL test purposes.
|
||||
*/
|
||||
post = PORT_Strstr(buffer->data, "POST ");
|
||||
if (!post || *post != 'P')
|
||||
break;
|
||||
|
||||
/* It's a post, so look for the next and final CR/LF. */
|
||||
/* We should parse content length here, but ... */
|
||||
while (buffer->index < buffer->dataEnd && newln < 3) {
|
||||
int octet = buffer->data[buffer->index++];
|
||||
if (octet == '\n') {
|
||||
newln++;
|
||||
}
|
||||
}
|
||||
|
||||
if (newln == 3)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Have either (a) a complete get, (b) a complete post, (c) EOF */
|
||||
|
||||
/* Execute a "GET " operation. */
|
||||
if (buffer->index > 0 && PORT_Strncmp(buffer->data, "GET ", 4) == 0) {
|
||||
int fnLength;
|
||||
|
||||
/* File name is the part after "GET ". */
|
||||
fnLength = strcspn(buffer->data + 5, " \r\n");
|
||||
*fileName = (char *)PORT_Alloc(fnLength + 1);
|
||||
PORT_Strncpy(*fileName, buffer->data + 5, fnLength);
|
||||
(*fileName)[fnLength] = '\0';
|
||||
}
|
||||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* Function: authenticateSocket()
|
||||
*
|
||||
* Purpose: Configure a socket for SSL.
|
||||
*
|
||||
*
|
||||
*/
|
||||
PRFileDesc *
|
||||
setupSSLSocket(PRFileDesc *tcpSocket, int requestCert)
|
||||
{
|
||||
PRFileDesc *sslSocket;
|
||||
SSLKEAType certKEA;
|
||||
int certErr = 0;
|
||||
SECStatus secStatus;
|
||||
|
||||
/* Set the appropriate flags. */
|
||||
|
||||
sslSocket = SSL_ImportFD(NULL, tcpSocket);
|
||||
if (sslSocket == NULL) {
|
||||
errWarn("SSL_ImportFD");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
secStatus = SSL_OptionSet(sslSocket, SSL_SECURITY, PR_TRUE);
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_OptionSet SSL_SECURITY");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
secStatus = SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_SERVER, PR_TRUE);
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_OptionSet:SSL_HANDSHAKE_AS_SERVER");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
secStatus = SSL_OptionSet(sslSocket, SSL_REQUEST_CERTIFICATE,
|
||||
(requestCert >= REQUEST_CERT_ONCE));
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_OptionSet:SSL_REQUEST_CERTIFICATE");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
secStatus = SSL_OptionSet(sslSocket, SSL_REQUIRE_CERTIFICATE,
|
||||
(requestCert == REQUIRE_CERT_ONCE));
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_OptionSet:SSL_REQUIRE_CERTIFICATE");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* Set the appropriate callback routines. */
|
||||
|
||||
secStatus = SSL_AuthCertificateHook(sslSocket, myAuthCertificate,
|
||||
CERT_GetDefaultCertDB());
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_AuthCertificateHook");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
secStatus = SSL_BadCertHook(sslSocket,
|
||||
(SSLBadCertHandler)myBadCertHandler, &certErr);
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_BadCertHook");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
secStatus = SSL_HandshakeCallback(sslSocket,
|
||||
(SSLHandshakeCallback)myHandshakeCallback,
|
||||
NULL);
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_HandshakeCallback");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
secStatus = SSL_SetPKCS11PinArg(sslSocket, password);
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_HandshakeCallback");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
certKEA = NSS_FindCertKEAType(cert);
|
||||
|
||||
secStatus = SSL_ConfigSecureServer(sslSocket, cert, privKey, certKEA);
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_ConfigSecureServer");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
return sslSocket;
|
||||
|
||||
loser:
|
||||
|
||||
PR_Close(tcpSocket);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Function: authenticateSocket()
|
||||
*
|
||||
* Purpose: Perform client authentication on the socket.
|
||||
*
|
||||
*/
|
||||
SECStatus
|
||||
authenticateSocket(PRFileDesc *sslSocket, PRBool requireCert)
|
||||
{
|
||||
CERTCertificate *cert;
|
||||
SECStatus secStatus;
|
||||
|
||||
/* Returns NULL if client authentication is not enabled or if the
|
||||
* client had no certificate. */
|
||||
cert = SSL_PeerCertificate(sslSocket);
|
||||
if (cert) {
|
||||
/* Client had a certificate, so authentication is through. */
|
||||
CERT_DestroyCertificate(cert);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* Request client to authenticate itself. */
|
||||
secStatus = SSL_OptionSet(sslSocket, SSL_REQUEST_CERTIFICATE, PR_TRUE);
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_OptionSet:SSL_REQUEST_CERTIFICATE");
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* If desired, require client to authenticate itself. Note
|
||||
* SSL_REQUEST_CERTIFICATE must also be on, as above. */
|
||||
secStatus = SSL_OptionSet(sslSocket, SSL_REQUIRE_CERTIFICATE, requireCert);
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_OptionSet:SSL_REQUIRE_CERTIFICATE");
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Having changed socket configuration parameters, redo handshake. */
|
||||
secStatus = SSL_ReHandshake(sslSocket, PR_TRUE);
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_ReHandshake");
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Force the handshake to complete before moving on. */
|
||||
secStatus = SSL_ForceHandshake(sslSocket);
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_ForceHandshake");
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* Function: writeDataToSocket
|
||||
*
|
||||
* Purpose: Write the client's request back to the socket. If the client
|
||||
* requested a file, dump it to the socket.
|
||||
*
|
||||
*/
|
||||
SECStatus
|
||||
writeDataToSocket(PRFileDesc *sslSocket, DataBuffer *buffer, char *fileName)
|
||||
{
|
||||
int headerLength;
|
||||
int numBytes;
|
||||
char messageBuffer[120];
|
||||
PRFileDesc *local_file_fd = NULL;
|
||||
char header[] = "<html><body><h1>Sample SSL server</h1><br><br>";
|
||||
char filehd[] = "<h2>The file you requested:</h2><br>";
|
||||
char reqhd[] = "<h2>This is your request:</h2><br>";
|
||||
char link[] = "Try getting a <a HREF=\"../testfile\">file</a><br>";
|
||||
char footer[] = "<br><h2>End of request.</h2><br></body></html>";
|
||||
|
||||
headerLength = PORT_Strlen(defaultHeader);
|
||||
|
||||
/* Write a header to the socket. */
|
||||
numBytes = PR_Write(sslSocket, header, PORT_Strlen(header));
|
||||
if (numBytes < 0) {
|
||||
errWarn("PR_Write");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
if (fileName) {
|
||||
PRFileInfo info;
|
||||
PRStatus prStatus;
|
||||
|
||||
/* Try to open the local file named.
|
||||
* If successful, then write it to the client.
|
||||
*/
|
||||
prStatus = PR_GetFileInfo(fileName, &info);
|
||||
if (prStatus != PR_SUCCESS ||
|
||||
info.type != PR_FILE_FILE ||
|
||||
info.size < 0) {
|
||||
PORT_Free(fileName);
|
||||
/* Maybe a GET not sent from client.c? */
|
||||
goto writerequest;
|
||||
}
|
||||
|
||||
local_file_fd = PR_Open(fileName, PR_RDONLY, 0);
|
||||
if (local_file_fd == NULL) {
|
||||
PORT_Free(fileName);
|
||||
goto writerequest;
|
||||
}
|
||||
|
||||
/* Write a header to the socket. */
|
||||
numBytes = PR_Write(sslSocket, filehd, PORT_Strlen(filehd));
|
||||
if (numBytes < 0) {
|
||||
errWarn("PR_Write");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* Transmit the local file prepended by the default header
|
||||
* across the socket.
|
||||
*/
|
||||
numBytes = PR_TransmitFile(sslSocket, local_file_fd,
|
||||
defaultHeader, headerLength,
|
||||
PR_TRANSMITFILE_KEEP_OPEN,
|
||||
PR_INTERVAL_NO_TIMEOUT);
|
||||
|
||||
/* Error in transmission. */
|
||||
if (numBytes < 0) {
|
||||
errWarn("PR_TransmitFile");
|
||||
/*
|
||||
i = PORT_Strlen(errString);
|
||||
PORT_Memcpy(buf, errString, i);
|
||||
*/
|
||||
/* Transmitted bytes successfully. */
|
||||
} else {
|
||||
numBytes -= headerLength;
|
||||
fprintf(stderr, "PR_TransmitFile wrote %d bytes from %s\n",
|
||||
numBytes, fileName);
|
||||
}
|
||||
|
||||
PORT_Free(fileName);
|
||||
PR_Close(local_file_fd);
|
||||
}
|
||||
|
||||
writerequest:
|
||||
|
||||
/* Write a header to the socket. */
|
||||
numBytes = PR_Write(sslSocket, reqhd, PORT_Strlen(reqhd));
|
||||
if (numBytes < 0) {
|
||||
errWarn("PR_Write");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* Write the buffer data to the socket. */
|
||||
if (buffer->index <= 0) {
|
||||
/* Reached the EOF. Report incomplete transaction to socket. */
|
||||
PORT_Sprintf(messageBuffer,
|
||||
"GET or POST incomplete after %d bytes.\r\n",
|
||||
buffer->dataEnd);
|
||||
numBytes = PR_Write(sslSocket, messageBuffer,
|
||||
PORT_Strlen(messageBuffer));
|
||||
if (numBytes < 0) {
|
||||
errWarn("PR_Write");
|
||||
goto loser;
|
||||
}
|
||||
} else {
|
||||
/* Display the buffer data. */
|
||||
fwrite(buffer->data, 1, buffer->index, stdout);
|
||||
/* Write the buffer data to the socket. */
|
||||
numBytes = PR_Write(sslSocket, buffer->data, buffer->index);
|
||||
if (numBytes < 0) {
|
||||
errWarn("PR_Write");
|
||||
goto loser;
|
||||
}
|
||||
/* Display security information for the socket. */
|
||||
printSecurityInfo(sslSocket);
|
||||
/* Write any discarded data out to the socket. */
|
||||
if (buffer->index < buffer->dataEnd) {
|
||||
PORT_Sprintf(buffer->data, "Discarded %d characters.\r\n",
|
||||
buffer->dataEnd - buffer->index);
|
||||
numBytes = PR_Write(sslSocket, buffer->data,
|
||||
PORT_Strlen(buffer->data));
|
||||
if (numBytes < 0) {
|
||||
errWarn("PR_Write");
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Write a footer to the socket. */
|
||||
numBytes = PR_Write(sslSocket, footer, PORT_Strlen(footer));
|
||||
if (numBytes < 0) {
|
||||
errWarn("PR_Write");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* Write a link to the socket. */
|
||||
numBytes = PR_Write(sslSocket, link, PORT_Strlen(link));
|
||||
if (numBytes < 0) {
|
||||
errWarn("PR_Write");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* Complete the HTTP transaction. */
|
||||
numBytes = PR_Write(sslSocket, "EOF\r\n\r\n\r\n", 9);
|
||||
if (numBytes < 0) {
|
||||
errWarn("PR_Write");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* Do a nice shutdown if asked. */
|
||||
if (!strncmp(buffer->data, stopCmd, strlen(stopCmd))) {
|
||||
stopping = 1;
|
||||
}
|
||||
return SECSuccess;
|
||||
|
||||
loser:
|
||||
|
||||
/* Do a nice shutdown if asked. */
|
||||
if (!strncmp(buffer->data, stopCmd, strlen(stopCmd))) {
|
||||
stopping = 1;
|
||||
}
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Function: int handle_connection()
|
||||
*
|
||||
* Purpose: Thread to handle a connection to a socket.
|
||||
*
|
||||
*/
|
||||
SECStatus
|
||||
handle_connection(void *tcp_sock, int requestCert)
|
||||
{
|
||||
PRFileDesc * tcpSocket = (PRFileDesc *)tcp_sock;
|
||||
PRFileDesc * sslSocket = NULL;
|
||||
SECStatus secStatus = SECFailure;
|
||||
PRStatus prStatus;
|
||||
PRSocketOptionData socketOption;
|
||||
DataBuffer buffer;
|
||||
char * fileName = NULL;
|
||||
|
||||
/* Initialize the data buffer. */
|
||||
memset(buffer.data, 0, BUFFER_SIZE);
|
||||
buffer.remaining = BUFFER_SIZE;
|
||||
buffer.index = 0;
|
||||
buffer.dataStart = 0;
|
||||
buffer.dataEnd = 0;
|
||||
|
||||
/* Make sure the socket is blocking. */
|
||||
socketOption.option = PR_SockOpt_Nonblocking;
|
||||
socketOption.value.non_blocking = PR_FALSE;
|
||||
PR_SetSocketOption(tcpSocket, &socketOption);
|
||||
|
||||
sslSocket = setupSSLSocket(tcpSocket, requestCert);
|
||||
if (sslSocket == NULL) {
|
||||
errWarn("setupSSLSocket");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
secStatus = SSL_ResetHandshake(sslSocket, /* asServer */ PR_TRUE);
|
||||
if (secStatus != SECSuccess) {
|
||||
errWarn("SSL_ResetHandshake");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Read data from the socket, parse it for HTTP content.
|
||||
* If the user is requesting/requiring authentication, authenticate
|
||||
* the socket. Then write the result back to the socket. */
|
||||
fprintf(stdout, "\nReading data from socket...\n\n");
|
||||
secStatus = readDataFromSocket(sslSocket, &buffer, &fileName);
|
||||
if (secStatus != SECSuccess) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (requestCert >= REQUEST_CERT_ALL) {
|
||||
fprintf(stdout, "\nAuthentication requested.\n\n");
|
||||
secStatus = authenticateSocket(sslSocket,
|
||||
(requestCert == REQUIRE_CERT_ALL));
|
||||
if (secStatus != SECSuccess) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stdout, "\nWriting data to socket...\n\n");
|
||||
secStatus = writeDataToSocket(sslSocket, &buffer, fileName);
|
||||
|
||||
cleanup:
|
||||
|
||||
/* Close down the socket. */
|
||||
prStatus = PR_Close(tcpSocket);
|
||||
if (prStatus != PR_SUCCESS) {
|
||||
errWarn("PR_Close");
|
||||
}
|
||||
|
||||
return secStatus;
|
||||
}
|
||||
|
||||
/* Function: int accept_connection()
|
||||
*
|
||||
* Purpose: Thread to accept a connection to the socket.
|
||||
*
|
||||
*/
|
||||
SECStatus
|
||||
accept_connection(void *listener, int requestCert)
|
||||
{
|
||||
PRFileDesc *listenSocket = (PRFileDesc*)listener;
|
||||
PRNetAddr addr;
|
||||
PRStatus prStatus;
|
||||
|
||||
/* XXX need an SSL socket here? */
|
||||
while (!stopping) {
|
||||
PRFileDesc *tcpSocket;
|
||||
SECStatus result;
|
||||
|
||||
fprintf(stderr, "\n\n\nAbout to call accept.\n");
|
||||
|
||||
/* Accept a connection to the socket. */
|
||||
tcpSocket = PR_Accept(listenSocket, &addr, PR_INTERVAL_NO_TIMEOUT);
|
||||
if (tcpSocket == NULL) {
|
||||
errWarn("PR_Accept");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Accepted the connection, now handle it. */
|
||||
result = launch_thread(&threadMGR, handle_connection,
|
||||
tcpSocket, requestCert);
|
||||
|
||||
if (result != SECSuccess) {
|
||||
prStatus = PR_Close(tcpSocket);
|
||||
if (prStatus != PR_SUCCESS) {
|
||||
exitErr("PR_Close");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Closing listen socket.\n");
|
||||
|
||||
prStatus = PR_Close(listenSocket);
|
||||
if (prStatus != PR_SUCCESS) {
|
||||
exitErr("PR_Close");
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* Function: void server_main()
|
||||
*
|
||||
* Purpose: This is the server's main function. It configures a socket
|
||||
* and listens to it.
|
||||
*
|
||||
*/
|
||||
void
|
||||
server_main(
|
||||
unsigned short port,
|
||||
int requestCert,
|
||||
SECKEYPrivateKey * privKey,
|
||||
CERTCertificate * cert,
|
||||
PRBool disableSSL3)
|
||||
{
|
||||
SECStatus secStatus;
|
||||
PRStatus prStatus;
|
||||
PRFileDesc * listenSocket;
|
||||
PRNetAddr addr;
|
||||
PRSocketOptionData socketOption;
|
||||
|
||||
/* Create a new socket. */
|
||||
listenSocket = PR_NewTCPSocket();
|
||||
if (listenSocket == NULL) {
|
||||
exitErr("PR_NewTCPSocket");
|
||||
}
|
||||
|
||||
/* Set socket to be blocking -
|
||||
* on some platforms the default is nonblocking.
|
||||
*/
|
||||
socketOption.option = PR_SockOpt_Nonblocking;
|
||||
socketOption.value.non_blocking = PR_FALSE;
|
||||
|
||||
prStatus = PR_SetSocketOption(listenSocket, &socketOption);
|
||||
if (prStatus != PR_SUCCESS) {
|
||||
exitErr("PR_SetSocketOption");
|
||||
}
|
||||
|
||||
/* This cipher is not on by default. The Acceptance test
|
||||
* would like it to be. Turn this cipher on.
|
||||
*/
|
||||
secStatus = SSL_CipherPrefSetDefault(SSL_RSA_WITH_NULL_MD5, PR_TRUE);
|
||||
if (secStatus != SECSuccess) {
|
||||
exitErr("SSL_CipherPrefSetDefault:SSL_RSA_WITH_NULL_MD5");
|
||||
}
|
||||
|
||||
/* Configure the network connection. */
|
||||
addr.inet.family = PR_AF_INET;
|
||||
addr.inet.ip = PR_INADDR_ANY;
|
||||
addr.inet.port = PR_htons(port);
|
||||
|
||||
/* Bind the address to the listener socket. */
|
||||
prStatus = PR_Bind(listenSocket, &addr);
|
||||
if (prStatus != PR_SUCCESS) {
|
||||
exitErr("PR_Bind");
|
||||
}
|
||||
|
||||
/* Listen for connection on the socket. The second argument is
|
||||
* the maximum size of the queue for pending connections.
|
||||
*/
|
||||
prStatus = PR_Listen(listenSocket, 5);
|
||||
if (prStatus != PR_SUCCESS) {
|
||||
exitErr("PR_Listen");
|
||||
}
|
||||
|
||||
/* Launch thread to handle connections to the socket. */
|
||||
secStatus = launch_thread(&threadMGR, accept_connection,
|
||||
listenSocket, requestCert);
|
||||
if (secStatus != SECSuccess) {
|
||||
PR_Close(listenSocket);
|
||||
} else {
|
||||
reap_threads(&threadMGR);
|
||||
destroy_thread_data(&threadMGR);
|
||||
}
|
||||
}
|
||||
|
||||
/* Function: int main()
|
||||
*
|
||||
* Purpose: Parses command arguments and configures SSL server.
|
||||
*
|
||||
*/
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char * progName = NULL;
|
||||
char * nickName = NULL;
|
||||
char * cipherString = NULL;
|
||||
char * dir = ".";
|
||||
int requestCert = 0;
|
||||
unsigned short port = 0;
|
||||
SECStatus secStatus;
|
||||
PRBool disableSSL3 = PR_FALSE;
|
||||
PLOptState * optstate;
|
||||
PLOptStatus status;
|
||||
|
||||
/* Zero out the thread manager. */
|
||||
PORT_Memset(&threadMGR, 0, sizeof(threadMGR));
|
||||
|
||||
progName = PL_strdup(argv[0]);
|
||||
|
||||
optstate = PL_CreateOptState(argc, argv, "3FRc:d:fp:n:rw:");
|
||||
while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
|
||||
switch(optstate->option) {
|
||||
case '3': disableSSL3 = PR_TRUE; break;
|
||||
case 'F': requestCert = REQUIRE_CERT_ALL; break;
|
||||
case 'R': requestCert = REQUEST_CERT_ALL; break;
|
||||
case 'c': cipherString = PL_strdup(optstate->value); break;
|
||||
case 'd': dir = PL_strdup(optstate->value); break;
|
||||
case 'f': requestCert = REQUIRE_CERT_ONCE; break;
|
||||
case 'n': nickName = PL_strdup(optstate->value); break;
|
||||
case 'p': port = PORT_Atoi(optstate->value); break;
|
||||
case 'r': requestCert = REQUEST_CERT_ONCE; break;
|
||||
case 'w': password = PL_strdup(optstate->value); break;
|
||||
default:
|
||||
case '?': Usage(progName);
|
||||
}
|
||||
}
|
||||
|
||||
if (nickName == NULL || port == 0)
|
||||
Usage(progName);
|
||||
|
||||
/* Call the NSPR initialization routines. */
|
||||
PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
|
||||
|
||||
/* Set the cert database password callback. */
|
||||
PK11_SetPasswordFunc(myPasswd);
|
||||
|
||||
/* Initialize NSS. */
|
||||
secStatus = NSS_Init(dir);
|
||||
if (secStatus != SECSuccess) {
|
||||
exitErr("NSS_Init");
|
||||
}
|
||||
|
||||
/* Set the policy for this server (REQUIRED - no default). */
|
||||
secStatus = NSS_SetDomesticPolicy();
|
||||
if (secStatus != SECSuccess) {
|
||||
exitErr("NSS_SetDomesticPolicy");
|
||||
}
|
||||
|
||||
/* XXX keep this? */
|
||||
/* all the SSL2 and SSL3 cipher suites are enabled by default. */
|
||||
if (cipherString) {
|
||||
int ndx;
|
||||
|
||||
/* disable all the ciphers, then enable the ones we want. */
|
||||
disableAllSSLCiphers();
|
||||
|
||||
while (0 != (ndx = *cipherString++)) {
|
||||
int *cptr;
|
||||
int cipher;
|
||||
|
||||
if (! isalpha(ndx))
|
||||
Usage(progName);
|
||||
cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites;
|
||||
for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0; )
|
||||
/* do nothing */;
|
||||
if (cipher) {
|
||||
SECStatus status;
|
||||
status = SSL_CipherPrefSetDefault(cipher, PR_TRUE);
|
||||
if (status != SECSuccess)
|
||||
errWarn("SSL_CipherPrefSetDefault()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get own certificate and private key. */
|
||||
cert = PK11_FindCertFromNickname(nickName, password);
|
||||
if (cert == NULL) {
|
||||
exitErr("PK11_FindCertFromNickname");
|
||||
}
|
||||
|
||||
privKey = PK11_FindKeyByAnyCert(cert, password);
|
||||
if (privKey == NULL) {
|
||||
exitErr("PK11_FindKeyByAnyCert");
|
||||
}
|
||||
|
||||
/* Configure the server's cache for a multi-process application
|
||||
* using default timeout values (24 hrs) and directory location (/tmp).
|
||||
*/
|
||||
SSL_ConfigMPServerSIDCache(256, 0, 0, NULL);
|
||||
|
||||
/* Launch server. */
|
||||
server_main(port, requestCert, privKey, cert, disableSSL3);
|
||||
|
||||
/* Shutdown NSS and exit NSPR gracefully. */
|
||||
NSS_Shutdown();
|
||||
PR_Cleanup();
|
||||
return 0;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
|
||||
CORE_DEPTH = ../../..
|
||||
|
||||
MODULE = security
|
||||
|
||||
EXPORTS =
|
||||
|
||||
CSRCS = server.c \
|
||||
sslsample.c \
|
||||
$(NULL)
|
||||
|
||||
PROGRAM = server
|
||||
|
||||
REQUIRES = dbm
|
||||
|
||||
DEFINES = -DNSPR20
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "nspr.h"
|
||||
|
||||
struct tuple_str {
|
||||
PRErrorCode errNum;
|
||||
const char * errString;
|
||||
};
|
||||
|
||||
typedef struct tuple_str tuple_str;
|
||||
|
||||
#define ER2(a,b) {a, b},
|
||||
#define ER3(a,b,c) {a, c},
|
||||
|
||||
#include "secerr.h"
|
||||
#include "sslerr.h"
|
||||
|
||||
const tuple_str errStrings[] = {
|
||||
|
||||
/* keep this list in asceding order of error numbers */
|
||||
#include "SSLerrs.h"
|
||||
#include "SECerrs.h"
|
||||
#include "NSPRerrs.h"
|
||||
|
||||
};
|
||||
|
||||
const PRInt32 numStrings = sizeof(errStrings) / sizeof(tuple_str);
|
||||
|
||||
/* Returns a UTF-8 encoded constant error string for "errNum".
|
||||
* Returns NULL of errNum is unknown.
|
||||
*/
|
||||
const char *
|
||||
SSL_Strerror(PRErrorCode errNum) {
|
||||
PRInt32 low = 0;
|
||||
PRInt32 high = numStrings - 1;
|
||||
PRInt32 i;
|
||||
PRErrorCode num;
|
||||
static int initDone;
|
||||
|
||||
/* make sure table is in ascending order.
|
||||
* binary search depends on it.
|
||||
*/
|
||||
if (!initDone) {
|
||||
PRErrorCode lastNum = (PRInt32)0x80000000;
|
||||
for (i = low; i <= high; ++i) {
|
||||
num = errStrings[i].errNum;
|
||||
if (num <= lastNum) {
|
||||
fprintf(stderr,
|
||||
"sequence error in error strings at item %d\n"
|
||||
"error %d (%s)\n"
|
||||
"should come after \n"
|
||||
"error %d (%s)\n",
|
||||
i, lastNum, errStrings[i-1].errString,
|
||||
num, errStrings[i].errString);
|
||||
}
|
||||
lastNum = num;
|
||||
}
|
||||
initDone = 1;
|
||||
}
|
||||
|
||||
/* Do binary search of table. */
|
||||
while (low + 1 < high) {
|
||||
i = (low + high) / 2;
|
||||
num = errStrings[i].errNum;
|
||||
if (errNum == num)
|
||||
return errStrings[i].errString;
|
||||
if (errNum < num)
|
||||
high = i;
|
||||
else
|
||||
low = i;
|
||||
}
|
||||
if (errNum == errStrings[low].errNum)
|
||||
return errStrings[low].errString;
|
||||
if (errNum == errStrings[high].errNum)
|
||||
return errStrings[high].errString;
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,590 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
#include "sslsample.h"
|
||||
#include "sslerror.h"
|
||||
|
||||
/* Declare SSL cipher suites. */
|
||||
|
||||
int ssl2CipherSuites[] = {
|
||||
SSL_EN_RC4_128_WITH_MD5, /* A */
|
||||
SSL_EN_RC4_128_EXPORT40_WITH_MD5, /* B */
|
||||
SSL_EN_RC2_128_CBC_WITH_MD5, /* C */
|
||||
SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, /* D */
|
||||
SSL_EN_DES_64_CBC_WITH_MD5, /* E */
|
||||
SSL_EN_DES_192_EDE3_CBC_WITH_MD5, /* F */
|
||||
0
|
||||
};
|
||||
|
||||
int ssl3CipherSuites[] = {
|
||||
SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, /* a */
|
||||
SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, /* b */
|
||||
SSL_RSA_WITH_RC4_128_MD5, /* c */
|
||||
SSL_RSA_WITH_3DES_EDE_CBC_SHA, /* d */
|
||||
SSL_RSA_WITH_DES_CBC_SHA, /* e */
|
||||
SSL_RSA_EXPORT_WITH_RC4_40_MD5, /* f */
|
||||
SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, /* g */
|
||||
SSL_FORTEZZA_DMS_WITH_NULL_SHA, /* h */
|
||||
SSL_RSA_WITH_NULL_MD5, /* i */
|
||||
SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, /* j */
|
||||
SSL_RSA_FIPS_WITH_DES_CBC_SHA, /* k */
|
||||
TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, /* l */
|
||||
TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, /* m */
|
||||
0
|
||||
};
|
||||
|
||||
/**************************************************************************
|
||||
**
|
||||
** SSL callback routines.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
/* Function: char * myPasswd()
|
||||
*
|
||||
* Purpose: This function is our custom password handler that is called by
|
||||
* SSL when retreiving private certs and keys from the database. Returns a
|
||||
* pointer to a string that with a password for the database. Password pointer
|
||||
* should point to dynamically allocated memory that will be freed later.
|
||||
*/
|
||||
char *
|
||||
myPasswd(PK11SlotInfo *info, PRBool retry, void *arg)
|
||||
{
|
||||
char * passwd = NULL;
|
||||
|
||||
if ( (!retry) && arg ) {
|
||||
passwd = PORT_Strdup((char *)arg);
|
||||
}
|
||||
|
||||
return passwd;
|
||||
}
|
||||
|
||||
/* Function: SECStatus myAuthCertificate()
|
||||
*
|
||||
* Purpose: This function is our custom certificate authentication handler.
|
||||
*
|
||||
* Note: This implementation is essentially the same as the default
|
||||
* SSL_AuthCertificate().
|
||||
*/
|
||||
SECStatus
|
||||
myAuthCertificate(void *arg, PRFileDesc *socket,
|
||||
PRBool checksig, PRBool isServer)
|
||||
{
|
||||
|
||||
SECCertUsage certUsage;
|
||||
CERTCertificate * cert;
|
||||
void * pinArg;
|
||||
char * hostName;
|
||||
SECStatus secStatus;
|
||||
|
||||
if (!arg || !socket) {
|
||||
errWarn("myAuthCertificate");
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Define how the cert is being used based upon the isServer flag. */
|
||||
|
||||
certUsage = isServer ? certUsageSSLClient : certUsageSSLServer;
|
||||
|
||||
cert = SSL_PeerCertificate(socket);
|
||||
|
||||
pinArg = SSL_RevealPinArg(socket);
|
||||
|
||||
secStatus = CERT_VerifyCertNow((CERTCertDBHandle *)arg,
|
||||
cert,
|
||||
checksig,
|
||||
certUsage,
|
||||
pinArg);
|
||||
|
||||
/* If this is a server, we're finished. */
|
||||
if (isServer || secStatus != SECSuccess) {
|
||||
CERT_DestroyCertificate(cert);
|
||||
return secStatus;
|
||||
}
|
||||
|
||||
/* Certificate is OK. Since this is the client side of an SSL
|
||||
* connection, we need to verify that the name field in the cert
|
||||
* matches the desired hostname. This is our defense against
|
||||
* man-in-the-middle attacks.
|
||||
*/
|
||||
|
||||
/* SSL_RevealURL returns a hostName, not an URL. */
|
||||
hostName = SSL_RevealURL(socket);
|
||||
|
||||
if (hostName && hostName[0]) {
|
||||
secStatus = CERT_VerifyCertName(cert, hostName);
|
||||
} else {
|
||||
PR_SetError(SSL_ERROR_BAD_CERT_DOMAIN, 0);
|
||||
secStatus = SECFailure;
|
||||
}
|
||||
|
||||
if (hostName)
|
||||
PR_Free(hostName);
|
||||
|
||||
CERT_DestroyCertificate(cert);
|
||||
return secStatus;
|
||||
}
|
||||
|
||||
/* Function: SECStatus myBadCertHandler()
|
||||
*
|
||||
* Purpose: This callback is called when the incoming certificate is not
|
||||
* valid. We define a certain set of parameters that still cause the
|
||||
* certificate to be "valid" for this session, and return SECSuccess to cause
|
||||
* the server to continue processing the request when any of these conditions
|
||||
* are met. Otherwise, SECFailure is return and the server rejects the
|
||||
* request.
|
||||
*/
|
||||
SECStatus
|
||||
myBadCertHandler(void *arg, PRFileDesc *socket)
|
||||
{
|
||||
|
||||
SECStatus secStatus = SECFailure;
|
||||
PRErrorCode err;
|
||||
|
||||
/* log invalid cert here */
|
||||
|
||||
if (!arg) {
|
||||
return secStatus;
|
||||
}
|
||||
|
||||
*(PRErrorCode *)arg = err = PORT_GetError();
|
||||
|
||||
/* If any of the cases in the switch are met, then we will proceed */
|
||||
/* with the processing of the request anyway. Otherwise, the default */
|
||||
/* case will be reached and we will reject the request. */
|
||||
|
||||
switch (err) {
|
||||
case SEC_ERROR_INVALID_AVA:
|
||||
case SEC_ERROR_INVALID_TIME:
|
||||
case SEC_ERROR_BAD_SIGNATURE:
|
||||
case SEC_ERROR_EXPIRED_CERTIFICATE:
|
||||
case SEC_ERROR_UNKNOWN_ISSUER:
|
||||
case SEC_ERROR_UNTRUSTED_CERT:
|
||||
case SEC_ERROR_CERT_VALID:
|
||||
case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
|
||||
case SEC_ERROR_CRL_EXPIRED:
|
||||
case SEC_ERROR_CRL_BAD_SIGNATURE:
|
||||
case SEC_ERROR_EXTENSION_VALUE_INVALID:
|
||||
case SEC_ERROR_CA_CERT_INVALID:
|
||||
case SEC_ERROR_CERT_USAGES_INVALID:
|
||||
case SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION:
|
||||
secStatus = SECSuccess;
|
||||
break;
|
||||
default:
|
||||
secStatus = SECFailure;
|
||||
break;
|
||||
}
|
||||
|
||||
printf("Bad certificate: %d, %s\n", err, SSL_Strerror(err));
|
||||
|
||||
return secStatus;
|
||||
}
|
||||
|
||||
/* Function: SECStatus ownGetClientAuthData()
|
||||
*
|
||||
* Purpose: This callback is used by SSL to pull client certificate
|
||||
* information upon server request.
|
||||
*/
|
||||
SECStatus
|
||||
myGetClientAuthData(void *arg,
|
||||
PRFileDesc *socket,
|
||||
struct CERTDistNamesStr *caNames,
|
||||
struct CERTCertificateStr **pRetCert,
|
||||
struct SECKEYPrivateKeyStr **pRetKey)
|
||||
{
|
||||
|
||||
CERTCertificate * cert;
|
||||
SECKEYPrivateKey * privKey;
|
||||
char * chosenNickName = (char *)arg;
|
||||
void * proto_win = NULL;
|
||||
SECStatus secStatus = SECFailure;
|
||||
|
||||
proto_win = SSL_RevealPinArg(socket);
|
||||
|
||||
if (chosenNickName) {
|
||||
cert = PK11_FindCertFromNickname(chosenNickName, proto_win);
|
||||
if (cert) {
|
||||
privKey = PK11_FindKeyByAnyCert(cert, proto_win);
|
||||
if (privKey) {
|
||||
secStatus = SECSuccess;
|
||||
} else {
|
||||
CERT_DestroyCertificate(cert);
|
||||
}
|
||||
}
|
||||
} else { /* no nickname given, automatically find the right cert */
|
||||
CERTCertNicknames *names;
|
||||
int i;
|
||||
|
||||
names = CERT_GetCertNicknames(CERT_GetDefaultCertDB(),
|
||||
SEC_CERT_NICKNAMES_USER, proto_win);
|
||||
|
||||
if (names != NULL) {
|
||||
for(i = 0; i < names->numnicknames; i++ ) {
|
||||
|
||||
cert = PK11_FindCertFromNickname(names->nicknames[i],
|
||||
proto_win);
|
||||
if (!cert) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Only check unexpired certs */
|
||||
if (CERT_CheckCertValidTimes(cert, PR_Now(), PR_FALSE)
|
||||
!= secCertTimeValid ) {
|
||||
CERT_DestroyCertificate(cert);
|
||||
continue;
|
||||
}
|
||||
|
||||
secStatus = NSS_CmpCertChainWCANames(cert, caNames);
|
||||
if (secStatus == SECSuccess) {
|
||||
privKey = PK11_FindKeyByAnyCert(cert, proto_win);
|
||||
if (privKey) {
|
||||
break;
|
||||
}
|
||||
secStatus = SECFailure;
|
||||
break;
|
||||
}
|
||||
CERT_FreeNicknames(names);
|
||||
} /* for loop */
|
||||
}
|
||||
}
|
||||
|
||||
if (secStatus == SECSuccess) {
|
||||
*pRetCert = cert;
|
||||
*pRetKey = privKey;
|
||||
}
|
||||
|
||||
return secStatus;
|
||||
}
|
||||
|
||||
/* Function: SECStatus myHandshakeCallback()
|
||||
*
|
||||
* Purpose: Called by SSL to inform application that the handshake is
|
||||
* complete. This function is mostly used on the server side of an SSL
|
||||
* connection, although it is provided for a client as well.
|
||||
* Useful when a non-blocking SSL_ReHandshake or SSL_ResetHandshake
|
||||
* is used to initiate a handshake.
|
||||
*
|
||||
* A typical scenario would be:
|
||||
*
|
||||
* 1. Server accepts an SSL connection from the client without client auth.
|
||||
* 2. Client sends a request.
|
||||
* 3. Server determines that to service request it needs to authenticate the
|
||||
* client and initiates another handshake requesting client auth.
|
||||
* 4. While handshake is in progress, server can do other work or spin waiting
|
||||
* for the handshake to complete.
|
||||
* 5. Server is notified that handshake has been successfully completed by
|
||||
* the custom handshake callback function and it can service the client's
|
||||
* request.
|
||||
*
|
||||
* Note: This function is not implemented in this sample, as we are using
|
||||
* blocking sockets.
|
||||
*/
|
||||
SECStatus
|
||||
myHandshakeCallback(PRFileDesc *socket, void *arg)
|
||||
{
|
||||
printf("Handshake has completed, ready to send data securely.\n");
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**
|
||||
** Routines for disabling SSL ciphers.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
void
|
||||
disableAllSSLCiphers(void)
|
||||
{
|
||||
const PRUint16 *cipherSuites = SSL_ImplementedCiphers;
|
||||
int i = SSL_NumImplementedCiphers;
|
||||
SECStatus rv;
|
||||
|
||||
/* disable all the SSL3 cipher suites */
|
||||
while (--i >= 0) {
|
||||
PRUint16 suite = cipherSuites[i];
|
||||
rv = SSL_CipherPrefSetDefault(suite, PR_FALSE);
|
||||
if (rv != SECSuccess) {
|
||||
printf("SSL_CipherPrefSetDefault didn't like value 0x%04x (i = %d)\n",
|
||||
suite, i);
|
||||
errWarn("SSL_CipherPrefSetDefault");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
**
|
||||
** Error and information routines.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
void
|
||||
errWarn(char *function)
|
||||
{
|
||||
PRErrorCode errorNumber = PR_GetError();
|
||||
const char * errorString = SSL_Strerror(errorNumber);
|
||||
|
||||
printf("Error in function %s: %d\n - %s\n",
|
||||
function, errorNumber, errorString);
|
||||
}
|
||||
|
||||
void
|
||||
exitErr(char *function)
|
||||
{
|
||||
errWarn(function);
|
||||
/* Exit gracefully. */
|
||||
NSS_Shutdown();
|
||||
PR_Cleanup();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
printSecurityInfo(PRFileDesc *fd)
|
||||
{
|
||||
char * cp; /* bulk cipher name */
|
||||
char * ip; /* cert issuer DN */
|
||||
char * sp; /* cert subject DN */
|
||||
int op; /* High, Low, Off */
|
||||
int kp0; /* total key bits */
|
||||
int kp1; /* secret key bits */
|
||||
int result;
|
||||
SSL3Statistics * ssl3stats = SSL_GetStatistics();
|
||||
|
||||
result = SSL_SecurityStatus(fd, &op, &cp, &kp0, &kp1, &ip, &sp);
|
||||
if (result != SECSuccess)
|
||||
return;
|
||||
printf("bulk cipher %s, %d secret key bits, %d key bits, status: %d\n"
|
||||
"subject DN: %s\n"
|
||||
"issuer DN: %s\n", cp, kp1, kp0, op, sp, ip);
|
||||
PR_Free(cp);
|
||||
PR_Free(ip);
|
||||
PR_Free(sp);
|
||||
|
||||
printf("%ld cache hits; %ld cache misses, %ld cache not reusable\n",
|
||||
ssl3stats->hch_sid_cache_hits, ssl3stats->hch_sid_cache_misses,
|
||||
ssl3stats->hch_sid_cache_not_ok);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
** Begin thread management routines and data.
|
||||
**************************************************************************/
|
||||
|
||||
void
|
||||
thread_wrapper(void * arg)
|
||||
{
|
||||
GlobalThreadMgr *threadMGR = (GlobalThreadMgr *)arg;
|
||||
perThread *slot = &threadMGR->threads[threadMGR->index];
|
||||
|
||||
/* wait for parent to finish launching us before proceeding. */
|
||||
PR_Lock(threadMGR->threadLock);
|
||||
PR_Unlock(threadMGR->threadLock);
|
||||
|
||||
slot->rv = (* slot->startFunc)(slot->a, slot->b);
|
||||
|
||||
PR_Lock(threadMGR->threadLock);
|
||||
slot->running = rs_zombie;
|
||||
|
||||
/* notify the thread exit handler. */
|
||||
PR_NotifyCondVar(threadMGR->threadEndQ);
|
||||
|
||||
PR_Unlock(threadMGR->threadLock);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
launch_thread(GlobalThreadMgr *threadMGR,
|
||||
startFn *startFunc,
|
||||
void *a,
|
||||
int b)
|
||||
{
|
||||
perThread *slot;
|
||||
int i;
|
||||
|
||||
if (!threadMGR->threadStartQ) {
|
||||
threadMGR->threadLock = PR_NewLock();
|
||||
threadMGR->threadStartQ = PR_NewCondVar(threadMGR->threadLock);
|
||||
threadMGR->threadEndQ = PR_NewCondVar(threadMGR->threadLock);
|
||||
}
|
||||
PR_Lock(threadMGR->threadLock);
|
||||
while (threadMGR->numRunning >= MAX_THREADS) {
|
||||
PR_WaitCondVar(threadMGR->threadStartQ, PR_INTERVAL_NO_TIMEOUT);
|
||||
}
|
||||
for (i = 0; i < threadMGR->numUsed; ++i) {
|
||||
slot = &threadMGR->threads[i];
|
||||
if (slot->running == rs_idle)
|
||||
break;
|
||||
}
|
||||
if (i >= threadMGR->numUsed) {
|
||||
if (i >= MAX_THREADS) {
|
||||
/* something's really wrong here. */
|
||||
PORT_Assert(i < MAX_THREADS);
|
||||
PR_Unlock(threadMGR->threadLock);
|
||||
return SECFailure;
|
||||
}
|
||||
++(threadMGR->numUsed);
|
||||
PORT_Assert(threadMGR->numUsed == i + 1);
|
||||
slot = &threadMGR->threads[i];
|
||||
}
|
||||
|
||||
slot->a = a;
|
||||
slot->b = b;
|
||||
slot->startFunc = startFunc;
|
||||
|
||||
threadMGR->index = i;
|
||||
|
||||
slot->prThread = PR_CreateThread(PR_USER_THREAD,
|
||||
thread_wrapper, threadMGR,
|
||||
PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
|
||||
PR_JOINABLE_THREAD, 0);
|
||||
|
||||
if (slot->prThread == NULL) {
|
||||
PR_Unlock(threadMGR->threadLock);
|
||||
printf("Failed to launch thread!\n");
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
slot->inUse = 1;
|
||||
slot->running = 1;
|
||||
++(threadMGR->numRunning);
|
||||
PR_Unlock(threadMGR->threadLock);
|
||||
printf("Launched thread in slot %d \n", threadMGR->index);
|
||||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
reap_threads(GlobalThreadMgr *threadMGR)
|
||||
{
|
||||
perThread * slot;
|
||||
int i;
|
||||
|
||||
if (!threadMGR->threadLock)
|
||||
return 0;
|
||||
PR_Lock(threadMGR->threadLock);
|
||||
while (threadMGR->numRunning > 0) {
|
||||
PR_WaitCondVar(threadMGR->threadEndQ, PR_INTERVAL_NO_TIMEOUT);
|
||||
for (i = 0; i < threadMGR->numUsed; ++i) {
|
||||
slot = &threadMGR->threads[i];
|
||||
if (slot->running == rs_zombie) {
|
||||
/* Handle cleanup of thread here. */
|
||||
printf("Thread in slot %d returned %d\n", i, slot->rv);
|
||||
|
||||
/* Now make sure the thread has ended OK. */
|
||||
PR_JoinThread(slot->prThread);
|
||||
slot->running = rs_idle;
|
||||
--threadMGR->numRunning;
|
||||
|
||||
/* notify the thread launcher. */
|
||||
PR_NotifyCondVar(threadMGR->threadStartQ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Safety Sam sez: make sure count is right. */
|
||||
for (i = 0; i < threadMGR->numUsed; ++i) {
|
||||
slot = &threadMGR->threads[i];
|
||||
if (slot->running != rs_idle) {
|
||||
fprintf(stderr, "Thread in slot %d is in state %d!\n",
|
||||
i, slot->running);
|
||||
}
|
||||
}
|
||||
PR_Unlock(threadMGR->threadLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
destroy_thread_data(GlobalThreadMgr *threadMGR)
|
||||
{
|
||||
PORT_Memset(threadMGR->threads, 0, sizeof(threadMGR->threads));
|
||||
|
||||
if (threadMGR->threadEndQ) {
|
||||
PR_DestroyCondVar(threadMGR->threadEndQ);
|
||||
threadMGR->threadEndQ = NULL;
|
||||
}
|
||||
if (threadMGR->threadStartQ) {
|
||||
PR_DestroyCondVar(threadMGR->threadStartQ);
|
||||
threadMGR->threadStartQ = NULL;
|
||||
}
|
||||
if (threadMGR->threadLock) {
|
||||
PR_DestroyLock(threadMGR->threadLock);
|
||||
threadMGR->threadLock = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
** End thread management routines.
|
||||
**************************************************************************/
|
||||
|
||||
void
|
||||
lockedVars_Init( lockedVars * lv)
|
||||
{
|
||||
lv->count = 0;
|
||||
lv->waiters = 0;
|
||||
lv->lock = PR_NewLock();
|
||||
lv->condVar = PR_NewCondVar(lv->lock);
|
||||
}
|
||||
|
||||
void
|
||||
lockedVars_Destroy( lockedVars * lv)
|
||||
{
|
||||
PR_DestroyCondVar(lv->condVar);
|
||||
lv->condVar = NULL;
|
||||
|
||||
PR_DestroyLock(lv->lock);
|
||||
lv->lock = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
lockedVars_WaitForDone(lockedVars * lv)
|
||||
{
|
||||
PR_Lock(lv->lock);
|
||||
while (lv->count > 0) {
|
||||
PR_WaitCondVar(lv->condVar, PR_INTERVAL_NO_TIMEOUT);
|
||||
}
|
||||
PR_Unlock(lv->lock);
|
||||
}
|
||||
|
||||
int /* returns count */
|
||||
lockedVars_AddToCount(lockedVars * lv, int addend)
|
||||
{
|
||||
int rv;
|
||||
|
||||
PR_Lock(lv->lock);
|
||||
rv = lv->count += addend;
|
||||
if (rv <= 0) {
|
||||
PR_NotifyCondVar(lv->condVar);
|
||||
}
|
||||
PR_Unlock(lv->lock);
|
||||
return rv;
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
#ifndef SSLSAMPLE_H
|
||||
#define SSLSAMPLE_H
|
||||
|
||||
/* Generic header files */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* NSPR header files */
|
||||
|
||||
#include "nspr.h"
|
||||
#include "prerror.h"
|
||||
#include "prnetdb.h"
|
||||
|
||||
/* NSS header files */
|
||||
|
||||
#include "pk11func.h"
|
||||
#include "secitem.h"
|
||||
#include "ssl.h"
|
||||
#include "certt.h"
|
||||
#include "nss.h"
|
||||
#include "secrng.h"
|
||||
#include "secder.h"
|
||||
#include "key.h"
|
||||
#include "sslproto.h"
|
||||
|
||||
/* Custom header files */
|
||||
|
||||
/*
|
||||
#include "sslerror.h"
|
||||
*/
|
||||
|
||||
#define BUFFER_SIZE 10240
|
||||
|
||||
/* Declare SSL cipher suites. */
|
||||
|
||||
extern int cipherSuites[];
|
||||
extern int ssl2CipherSuites[];
|
||||
extern int ssl3CipherSuites[];
|
||||
|
||||
/* Data buffer read from a socket. */
|
||||
typedef struct DataBufferStr {
|
||||
char data[BUFFER_SIZE];
|
||||
int index;
|
||||
int remaining;
|
||||
int dataStart;
|
||||
int dataEnd;
|
||||
} DataBuffer;
|
||||
|
||||
/* SSL callback routines. */
|
||||
|
||||
char * myPasswd(PK11SlotInfo *info, PRBool retry, void *arg);
|
||||
|
||||
SECStatus myAuthCertificate(void *arg, PRFileDesc *socket,
|
||||
PRBool checksig, PRBool isServer);
|
||||
|
||||
SECStatus myBadCertHandler(void *arg, PRFileDesc *socket);
|
||||
|
||||
SECStatus myHandshakeCallback(PRFileDesc *socket, void *arg);
|
||||
|
||||
SECStatus myGetClientAuthData(void *arg, PRFileDesc *socket,
|
||||
struct CERTDistNamesStr *caNames,
|
||||
struct CERTCertificateStr **pRetCert,
|
||||
struct SECKEYPrivateKeyStr **pRetKey);
|
||||
|
||||
/* Disable all v2/v3 SSL ciphers. */
|
||||
|
||||
void disableAllSSLCiphers(void);
|
||||
|
||||
|
||||
/* Error and information utilities. */
|
||||
|
||||
void errWarn(char *function);
|
||||
|
||||
void exitErr(char *function);
|
||||
|
||||
void printSecurityInfo(PRFileDesc *fd);
|
||||
|
||||
/* Some simple thread management routines. */
|
||||
|
||||
#define MAX_THREADS 32
|
||||
|
||||
typedef SECStatus startFn(void *a, int b);
|
||||
|
||||
typedef enum { rs_idle = 0, rs_running = 1, rs_zombie = 2 } runState;
|
||||
|
||||
typedef struct perThreadStr {
|
||||
PRFileDesc *a;
|
||||
int b;
|
||||
int rv;
|
||||
startFn *startFunc;
|
||||
PRThread *prThread;
|
||||
PRBool inUse;
|
||||
runState running;
|
||||
} perThread;
|
||||
|
||||
typedef struct GlobalThreadMgrStr {
|
||||
PRLock *threadLock;
|
||||
PRCondVar *threadStartQ;
|
||||
PRCondVar *threadEndQ;
|
||||
perThread threads[MAX_THREADS];
|
||||
int index;
|
||||
int numUsed;
|
||||
int numRunning;
|
||||
} GlobalThreadMgr;
|
||||
|
||||
void thread_wrapper(void * arg);
|
||||
|
||||
SECStatus launch_thread(GlobalThreadMgr *threadMGR,
|
||||
startFn *startFunc, void *a, int b);
|
||||
|
||||
SECStatus reap_threads(GlobalThreadMgr *threadMGR);
|
||||
|
||||
void destroy_thread_data(GlobalThreadMgr *threadMGR);
|
||||
|
||||
/* Management of locked variables. */
|
||||
|
||||
struct lockedVarsStr {
|
||||
PRLock * lock;
|
||||
int count;
|
||||
int waiters;
|
||||
PRCondVar * condVar;
|
||||
};
|
||||
|
||||
typedef struct lockedVarsStr lockedVars;
|
||||
|
||||
void lockedVars_Init(lockedVars *lv);
|
||||
|
||||
void lockedVars_Destroy(lockedVars *lv);
|
||||
|
||||
void lockedVars_WaitForDone(lockedVars *lv);
|
||||
|
||||
int lockedVars_AddToCount(lockedVars *lv, int addend);
|
||||
|
||||
/* Buffer stuff. */
|
||||
|
||||
static const char stopCmd[] = { "GET /stop " };
|
||||
static const char defaultHeader[] = {
|
||||
"HTTP/1.0 200 OK\r\n"
|
||||
"Server: SSL sample server\r\n"
|
||||
"Content-type: text/plain\r\n"
|
||||
"\r\n"
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,76 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
|
||||
#######################################################################
|
||||
# (1) Include initial platform-independent assignments (MANDATORY). #
|
||||
#######################################################################
|
||||
|
||||
include manifest.mn
|
||||
|
||||
#######################################################################
|
||||
# (2) Include "global" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/config.mk
|
||||
|
||||
#######################################################################
|
||||
# (3) Include "component" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
#######################################################################
|
||||
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
include ../platlibs.mk
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (5) Execute "global" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/rules.mk
|
||||
|
||||
#######################################################################
|
||||
# (6) Execute "component" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (7) Execute "local" rules. (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
|
||||
include ../platrules.mk
|
||||
|
||||
@@ -1,338 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tool for converting builtin CA certs.
|
||||
*
|
||||
* $Id: addbuiltin.c,v 1.3 2001-06-29 14:09:25 mcgreer%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#include "nss.h"
|
||||
#include "cert.h"
|
||||
#include "certdb.h"
|
||||
#include "secutil.h"
|
||||
#include "pk11func.h"
|
||||
|
||||
void dumpbytes(unsigned char *buf, int len)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i < len; i++) {
|
||||
if ((i !=0) && ((i & 0xf) == 0)) {
|
||||
printf("\n");
|
||||
}
|
||||
printf("\\%03o",buf[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
char *getTrustString(unsigned int trust)
|
||||
{
|
||||
if (trust & CERTDB_TRUSTED) {
|
||||
if (trust & CERTDB_TRUSTED_CA) {
|
||||
return "CKT_NETSCAPE_TRUSTED_DELEGATOR|CKT_NETSCAPE_TRUSTED";
|
||||
} else {
|
||||
return "CKT_NETSCAPE_TRUSTED";
|
||||
}
|
||||
} else {
|
||||
if (trust & CERTDB_TRUSTED_CA) {
|
||||
return "CKT_NETSCAPE_TRUSTED_DELEGATOR";
|
||||
} else {
|
||||
return "CKT_NETSCAPE_VALID";
|
||||
}
|
||||
}
|
||||
return "CKT_NETSCAPE_VALID"; /* not reached */
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
ConvertCertificate(SECItem *sdder, char *nickname, CERTCertTrust *trust)
|
||||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
CERTCertificate *cert;
|
||||
unsigned char sha1_hash[SHA1_LENGTH];
|
||||
unsigned char md5_hash[MD5_LENGTH];
|
||||
|
||||
cert = CERT_DecodeDERCertificate(sdder, PR_FALSE, nickname);
|
||||
if (!cert) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
printf("\n#\n# Certificate \"%s\"\n#\n",nickname);
|
||||
printf("CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE\n");
|
||||
printf("CKA_TOKEN CK_BBOOL CK_TRUE\n");
|
||||
printf("CKA_PRIVATE CK_BBOOL CK_FALSE\n");
|
||||
printf("CKA_MODIFIABLE CK_BBOOL CK_FALSE\n");
|
||||
printf("CKA_LABEL UTF8 \"%s\"\n",nickname);
|
||||
printf("CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509\n");
|
||||
printf("CKA_SUBJECT MULTILINE_OCTAL\n");
|
||||
dumpbytes(cert->derSubject.data,cert->derSubject.len);
|
||||
printf("END\n");
|
||||
printf("CKA_ID UTF8 \"0\"\n");
|
||||
printf("CKA_ISSUER MULTILINE_OCTAL\n");
|
||||
dumpbytes(cert->derIssuer.data,cert->derIssuer.len);
|
||||
printf("END\n");
|
||||
printf("CKA_SERIAL_NUMBER MULTILINE_OCTAL\n");
|
||||
dumpbytes(cert->serialNumber.data,cert->serialNumber.len);
|
||||
printf("END\n");
|
||||
printf("CKA_VALUE MULTILINE_OCTAL\n");
|
||||
dumpbytes(sdder->data,sdder->len);
|
||||
printf("END\n");
|
||||
|
||||
PK11_HashBuf(SEC_OID_SHA1, sha1_hash, sdder->data, sdder->len);
|
||||
PK11_HashBuf(SEC_OID_MD5, md5_hash, sdder->data, sdder->len);
|
||||
printf("\n# Trust for Certificate \"%s\"\n",nickname);
|
||||
printf("CKA_CLASS CK_OBJECT_CLASS CKO_NETSCAPE_TRUST\n");
|
||||
printf("CKA_TOKEN CK_BBOOL CK_TRUE\n");
|
||||
printf("CKA_PRIVATE CK_BBOOL CK_FALSE\n");
|
||||
printf("CKA_MODIFIABLE CK_BBOOL CK_FALSE\n");
|
||||
printf("CKA_LABEL UTF8 \"%s\"\n",nickname);
|
||||
printf("CKA_CERT_SHA1_HASH MULTILINE_OCTAL\n");
|
||||
dumpbytes(sha1_hash,SHA1_LENGTH);
|
||||
printf("END\n");
|
||||
printf("CKA_CERT_MD5_HASH MULTILINE_OCTAL\n");
|
||||
dumpbytes(md5_hash,MD5_LENGTH);
|
||||
printf("END\n");
|
||||
|
||||
printf("CKA_TRUST_SERVER_AUTH CK_TRUST %s\n",
|
||||
getTrustString(trust->sslFlags));
|
||||
printf("CKA_TRUST_EMAIL_PROTECTION CK_TRUST %s\n",
|
||||
getTrustString(trust->emailFlags));
|
||||
printf("CKA_TRUST_CODE_SIGNING CK_TRUST %s\n",
|
||||
getTrustString(trust->objectSigningFlags));
|
||||
#ifdef notdef
|
||||
printf("CKA_TRUST_CLIENT_AUTH CK_TRUST CKT_NETSCAPE_TRUSTED\n");*/
|
||||
printf("CKA_TRUST_DIGITAL_SIGNATURE CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR\n");
|
||||
printf("CKA_TRUST_NON_REPUDIATION CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR\n");
|
||||
printf("CKA_TRUST_KEY_ENCIPHERMENT CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR\n");
|
||||
printf("CKA_TRUST_DATA_ENCIPHERMENT CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR\n");
|
||||
printf("CKA_TRUST_KEY_AGREEMENT CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR\n");
|
||||
printf("CKA_TRUST_KEY_CERT_SIGN CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR\n");
|
||||
#endif
|
||||
|
||||
|
||||
PORT_Free(sdder->data);
|
||||
return(rv);
|
||||
|
||||
}
|
||||
|
||||
printheader() {
|
||||
printf("# \n"
|
||||
"# The contents of this file are subject to the Mozilla Public\n"
|
||||
"# License Version 1.1 (the \"License\"); you may not use this file\n"
|
||||
"# except in compliance with the License. You may obtain a copy of\n"
|
||||
"# the License at http://www.mozilla.org/MPL/\n"
|
||||
"# \n"
|
||||
"# Software distributed under the License is distributed on an \"AS\n"
|
||||
"# IS\" basis, WITHOUT WARRANTY OF ANY KIND, either express or\n"
|
||||
"# implied. See the License for the specific language governing\n"
|
||||
"# rights and limitations under the License.\n"
|
||||
"# \n"
|
||||
"# The Original Code is the Netscape security libraries.\n"
|
||||
"# \n"
|
||||
"# The Initial Developer of the Original Code is Netscape\n"
|
||||
"# Communications Corporation. Portions created by Netscape are \n"
|
||||
"# Copyright (C) 1994-2000 Netscape Communications Corporation. All\n"
|
||||
"# Rights Reserved.\n"
|
||||
"# \n"
|
||||
"# Contributor(s):\n"
|
||||
"# \n"
|
||||
"# Alternatively, the contents of this file may be used under the\n"
|
||||
"# terms of the GNU General Public License Version 2 or later (the\n"
|
||||
"# \"GPL\"), in which case the provisions of the GPL are applicable \n"
|
||||
"# instead of those above. If you wish to allow use of your \n"
|
||||
"# version of this file only under the terms of the GPL and not to\n"
|
||||
"# allow others to use your version of this file under the MPL,\n"
|
||||
"# indicate your decision by deleting the provisions above and\n"
|
||||
"# replace them with the notice and other provisions required by\n"
|
||||
"# the GPL. If you do not delete the provisions above, a recipient\n"
|
||||
"# may use your version of this file under either the MPL or the\n"
|
||||
"# GPL.\n"
|
||||
"#\n"
|
||||
"CVS_ID \"@(#) $RCSfile: addbuiltin.c,v $ $Revision: 1.3 $ $Date: 2001-06-29 14:09:25 $ $Name: not supported by cvs2svn $\"\n"
|
||||
"\n"
|
||||
"#\n"
|
||||
"# certdata.txt\n"
|
||||
"#\n"
|
||||
"# This file contains the object definitions for the certs and other\n"
|
||||
"# information \"built into\" NSS.\n"
|
||||
"#\n"
|
||||
"# Object definitions:\n"
|
||||
"#\n"
|
||||
"# Certificates\n"
|
||||
"#\n"
|
||||
"# -- Attribute -- -- type -- -- value --\n"
|
||||
"# CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE\n"
|
||||
"# CKA_TOKEN CK_BBOOL CK_TRUE\n"
|
||||
"# CKA_PRIVATE CK_BBOOL CK_FALSE\n"
|
||||
"# CKA_MODIFIABLE CK_BBOOL CK_FALSE\n"
|
||||
"# CKA_LABEL UTF8 (varies)\n"
|
||||
"# CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509\n"
|
||||
"# CKA_SUBJECT DER+base64 (varies)\n"
|
||||
"# CKA_ID byte array (varies)\n"
|
||||
"# CKA_ISSUER DER+base64 (varies)\n"
|
||||
"# CKA_SERIAL_NUMBER DER+base64 (varies)\n"
|
||||
"# CKA_VALUE DER+base64 (varies)\n"
|
||||
"# CKA_NETSCAPE_EMAIL ASCII7 (unused here)\n"
|
||||
"#\n"
|
||||
"# Trust\n"
|
||||
"#\n"
|
||||
"# -- Attribute -- -- type -- -- value --\n"
|
||||
"# CKA_CLASS CK_OBJECT_CLASS CKO_TRUST\n"
|
||||
"# CKA_TOKEN CK_BBOOL CK_TRUE\n"
|
||||
"# CKA_PRIVATE CK_BBOOL CK_FALSE\n"
|
||||
"# CKA_MODIFIABLE CK_BBOOL CK_FALSE\n"
|
||||
"# CKA_LABEL UTF8 (varies)\n"
|
||||
"# CKA_ISSUER DER+base64 (varies)\n"
|
||||
"# CKA_SERIAL_NUMBER DER+base64 (varies)\n"
|
||||
"# CKA_CERT_HASH binary+base64 (varies)\n"
|
||||
"# CKA_EXPIRES CK_DATE (not used here)\n"
|
||||
"# CKA_TRUST_DIGITAL_SIGNATURE CK_TRUST (varies)\n"
|
||||
"# CKA_TRUST_NON_REPUDIATION CK_TRUST (varies)\n"
|
||||
"# CKA_TRUST_KEY_ENCIPHERMENT CK_TRUST (varies)\n"
|
||||
"# CKA_TRUST_DATA_ENCIPHERMENT CK_TRUST (varies)\n"
|
||||
"# CKA_TRUST_KEY_AGREEMENT CK_TRUST (varies)\n"
|
||||
"# CKA_TRUST_KEY_CERT_SIGN CK_TRUST (varies)\n"
|
||||
"# CKA_TRUST_CRL_SIGN CK_TRUST (varies)\n"
|
||||
"# CKA_TRUST_SERVER_AUTH CK_TRUST (varies)\n"
|
||||
"# CKA_TRUST_CLIENT_AUTH CK_TRUST (varies)\n"
|
||||
"# CKA_TRUST_CODE_SIGNING CK_TRUST (varies)\n"
|
||||
"# CKA_TRUST_EMAIL_PROTECTION CK_TRUST (varies)\n"
|
||||
"# CKA_TRUST_IPSEC_END_SYSTEM CK_TRUST (varies)\n"
|
||||
"# CKA_TRUST_IPSEC_TUNNEL CK_TRUST (varies)\n"
|
||||
"# CKA_TRUST_IPSEC_USER CK_TRUST (varies)\n"
|
||||
"# CKA_TRUST_TIME_STAMPING CK_TRUST (varies)\n"
|
||||
"# (other trust attributes can be defined)\n"
|
||||
"#\n"
|
||||
"\n"
|
||||
"#\n"
|
||||
"# The object to tell NSS that this is a root list and we don't\n"
|
||||
"# have to go looking for others.\n"
|
||||
"#\n"
|
||||
"BEGINDATA\n"
|
||||
"CKA_CLASS CK_OBJECT_CLASS CKO_NETSCAPE_BUILTIN_ROOT_LIST\n"
|
||||
"CKA_TOKEN CK_BBOOL CK_TRUE\n"
|
||||
"CKA_PRIVATE CK_BBOOL CK_FALSE\n"
|
||||
"CKA_MODIFIABLE CK_BBOOL CK_FALSE\n"
|
||||
"CKA_LABEL UTF8 \"Mozilla Builtin Roots\"\n");
|
||||
}
|
||||
|
||||
static void Usage(char *progName)
|
||||
{
|
||||
fprintf(stderr, "%s -n nickname -t trust\n", progName);
|
||||
fprintf(stderr,
|
||||
"read a der-encoded cert from stdin in, and output\n"
|
||||
"it to stdout in a format suitable for the builtin root module.\n"
|
||||
"example: %s -n MyCA -t \"C,C,C\" < myca.der >> certdata.txt\n"
|
||||
"(pipe through atob if the cert is b64-encoded)\n");
|
||||
fprintf(stderr, "%15s nickname to assign to builtin cert.\n",
|
||||
"-n nickname");
|
||||
fprintf(stderr, "%15s default trust flags (cCTpPuw).\n",
|
||||
"-t trust");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
enum {
|
||||
opt_Input = 0,
|
||||
opt_Nickname,
|
||||
opt_Trust
|
||||
};
|
||||
|
||||
static secuCommandFlag addbuiltin_options[] =
|
||||
{
|
||||
{ /* opt_Input */ 'i', PR_TRUE, 0, PR_FALSE },
|
||||
{ /* opt_Nickname */ 'n', PR_TRUE, 0, PR_FALSE },
|
||||
{ /* opt_Trust */ 't', PR_TRUE, 0, PR_FALSE }
|
||||
};
|
||||
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
SECStatus rv;
|
||||
char *nickname;
|
||||
char *trusts;
|
||||
char *progName;
|
||||
PRFileDesc *infile;
|
||||
CERTCertTrust trust = { 0 };
|
||||
SECItem derCert = { 0 };
|
||||
|
||||
secuCommand addbuiltin = { 0 };
|
||||
addbuiltin.numOptions = sizeof(addbuiltin_options)/sizeof(secuCommandFlag);
|
||||
addbuiltin.options = addbuiltin_options;
|
||||
|
||||
progName = strrchr(argv[0], '/');
|
||||
progName = progName ? progName+1 : argv[0];
|
||||
|
||||
rv = SECU_ParseCommandLine(argc, argv, progName, &addbuiltin);
|
||||
|
||||
if (rv != SECSuccess)
|
||||
Usage(progName);
|
||||
|
||||
if (!addbuiltin.options[opt_Nickname].activated &&
|
||||
!addbuiltin.options[opt_Trust].activated) {
|
||||
fprintf(stderr, "%s: you must specify both a nickname and trust.\n");
|
||||
Usage(progName);
|
||||
}
|
||||
|
||||
if (addbuiltin.options[opt_Input].activated) {
|
||||
infile = PR_Open(addbuiltin.options[opt_Input].arg, PR_RDONLY, 00660);
|
||||
if (!infile) {
|
||||
fprintf(stderr, "%s: failed to open input file.\n");
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
infile = PR_STDIN;
|
||||
}
|
||||
|
||||
nickname = strdup(addbuiltin.options[opt_Nickname].arg);
|
||||
trusts = strdup(addbuiltin.options[opt_Trust].arg);
|
||||
|
||||
NSS_NoDB_Init(NULL);
|
||||
|
||||
rv = CERT_DecodeTrustString(&trust, trusts);
|
||||
if (rv) {
|
||||
fprintf(stderr, "%s: incorrectly formatted trust string.\n", progName);
|
||||
Usage(progName);
|
||||
}
|
||||
|
||||
SECU_FileToItem(&derCert, infile);
|
||||
|
||||
/*printheader();*/
|
||||
|
||||
rv = ConvertCertificate(&derCert, nickname, &trust);
|
||||
if (rv) {
|
||||
fprintf(stderr, "%s: failed to convert certificate.\n", progName);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
NSS_Shutdown();
|
||||
|
||||
return(SECSuccess);
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
|
||||
CORE_DEPTH = ../../..
|
||||
|
||||
# MODULE public and private header directories are implicitly REQUIRED.
|
||||
MODULE = security
|
||||
|
||||
CSRCS = \
|
||||
addbuiltin.c \
|
||||
$(NULL)
|
||||
|
||||
# The MODULE is always implicitly required.
|
||||
# Listing it here in REQUIRES makes it appear twice in the cc command line.
|
||||
REQUIRES = dbm seccmd
|
||||
|
||||
PROGRAM = addbuiltin
|
||||
|
||||
USE_STATIC_LIBS = 1
|
||||
@@ -1,76 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
|
||||
#######################################################################
|
||||
# (1) Include initial platform-independent assignments (MANDATORY). #
|
||||
#######################################################################
|
||||
|
||||
include manifest.mn
|
||||
|
||||
#######################################################################
|
||||
# (2) Include "global" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/config.mk
|
||||
|
||||
#######################################################################
|
||||
# (3) Include "component" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
#######################################################################
|
||||
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
include ../platlibs.mk
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (5) Execute "global" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/rules.mk
|
||||
|
||||
#######################################################################
|
||||
# (6) Execute "component" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (7) Execute "local" rules. (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
|
||||
include ../platrules.mk
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
#include "plgetopt.h"
|
||||
#include "nssbase.h"
|
||||
#include "cmdutil.h"
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(XP_WIN) || (defined(__sun) && !defined(SVR4))
|
||||
#if !defined(WIN32)
|
||||
extern int fread(char *, size_t, size_t, FILE*);
|
||||
extern int fwrite(char *, size_t, size_t, FILE*);
|
||||
extern int fprintf(FILE *, char *, ...);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(WIN32)
|
||||
#include "fcntl.h"
|
||||
#include "io.h"
|
||||
#endif
|
||||
|
||||
static PRInt32
|
||||
output_binary (void *arg, const unsigned char *obuf, PRInt32 size)
|
||||
{
|
||||
FILE *outFile = arg;
|
||||
int nb;
|
||||
|
||||
nb = fwrite(obuf, 1, size, outFile);
|
||||
if (nb != size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return nb;
|
||||
}
|
||||
|
||||
static PRStatus
|
||||
decode_file(FILE *outFile, FILE *inFile)
|
||||
{
|
||||
NSSBase64Decoder *cx;
|
||||
int nb;
|
||||
PRStatus status = PR_FAILURE;
|
||||
char ibuf[4096];
|
||||
|
||||
cx = NSSBase64Decoder_Create(output_binary, outFile);
|
||||
if (!cx) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (feof(inFile)) break;
|
||||
nb = fread(ibuf, 1, sizeof(ibuf), inFile);
|
||||
if (nb != sizeof(ibuf)) {
|
||||
if (nb == 0) {
|
||||
if (ferror(inFile)) {
|
||||
goto loser;
|
||||
}
|
||||
/* eof */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
status = NSSBase64Decoder_Update(cx, ibuf, nb);
|
||||
if (status == PR_FAILURE) goto loser;
|
||||
}
|
||||
|
||||
return NSSBase64Decoder_Destroy(cx, PR_FALSE);
|
||||
|
||||
loser:
|
||||
(void) NSSBase64Decoder_Destroy(cx, PR_TRUE);
|
||||
return status;
|
||||
}
|
||||
|
||||
static void Usage(char *progName)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: %s [-i input] [-o output]\n",
|
||||
progName);
|
||||
fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
|
||||
"-i input");
|
||||
fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
|
||||
"-o output");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *progName;
|
||||
PRStatus rv;
|
||||
FILE *inFile, *outFile;
|
||||
PLOptState *optstate;
|
||||
PLOptStatus status;
|
||||
|
||||
inFile = 0;
|
||||
outFile = 0;
|
||||
progName = strrchr(argv[0], '/');
|
||||
progName = progName ? progName+1 : argv[0];
|
||||
|
||||
/* Parse command line arguments */
|
||||
optstate = PL_CreateOptState(argc, argv, "i:o:");
|
||||
while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
|
||||
switch (optstate->option) {
|
||||
case '?':
|
||||
Usage(progName);
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
inFile = fopen(optstate->value, "r");
|
||||
if (!inFile) {
|
||||
fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
|
||||
progName, optstate->value);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
outFile = fopen(optstate->value, "wb");
|
||||
if (!outFile) {
|
||||
fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
|
||||
progName, optstate->value);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!inFile) inFile = stdin;
|
||||
if (!outFile) {
|
||||
#if defined(WIN32)
|
||||
int smrv = _setmode(_fileno(stdout), _O_BINARY);
|
||||
if (smrv == -1) {
|
||||
fprintf(stderr,
|
||||
"%s: Cannot change stdout to binary mode. Use -o option instead.\n",
|
||||
progName);
|
||||
return smrv;
|
||||
}
|
||||
#endif
|
||||
outFile = stdout;
|
||||
}
|
||||
rv = decode_file(outFile, inFile);
|
||||
if (rv == PR_FAILURE) {
|
||||
CMD_PrintError("lossage (errno=%d)", errno);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
|
||||
VERBOSE = 1
|
||||
include <manifest.mn>
|
||||
|
||||
#cannot define PROGRAM in manifest compatibly with NT and UNIX
|
||||
PROGRAM = atob
|
||||
PROGRAM = ./$(OBJDIR)/$(PROGRAM).exe
|
||||
include <$(DEPTH)\config\config.mak>
|
||||
|
||||
# let manifest generate C_OBJS, it will prepend ./$(OBJDIR)/
|
||||
# rules.mak will append C_OBJS onto OBJS.
|
||||
# OBJS = $(CSRCS:.c=.obj)
|
||||
|
||||
# include files are looked for in $LINCS and $INCS.
|
||||
# $LINCS is in manifest.mnw, computed from REQUIRES=
|
||||
INCS = $(INCS) \
|
||||
-I$(DEPTH)/security/lib/cert \
|
||||
-I../include \
|
||||
$(NULL)
|
||||
|
||||
IGNORE_ME = \
|
||||
-I$(DEPTH)/security/lib/key \
|
||||
-I$(DEPTH)/security/lib/util \
|
||||
$(NULL)
|
||||
|
||||
|
||||
WINFE = $(DEPTH)/cmd/winfe/mkfiles$(MOZ_BITS)/x86Dbg
|
||||
|
||||
# these files are the content of libdbm
|
||||
DBM_LIB = \
|
||||
$(WINFE)/DB.obj \
|
||||
$(WINFE)/HASH.obj \
|
||||
$(WINFE)/H_BIGKEY.obj \
|
||||
$(WINFE)/H_PAGE.obj \
|
||||
$(WINFE)/H_LOG2.obj \
|
||||
$(WINFE)/H_FUNC.obj \
|
||||
$(WINFE)/HASH_BUF.obj \
|
||||
$(NULL)
|
||||
|
||||
MOZ_LIBS = \
|
||||
$(WINFE)/ALLXPSTR.obj \
|
||||
$(WINFE)/XP_ERROR.obj \
|
||||
$(WINFE)/XPASSERT.obj \
|
||||
$(WINFE)/XP_REG.obj \
|
||||
$(WINFE)/XP_TRACE.obj \
|
||||
$(DBM_LIB) \
|
||||
$(WINFE)/XP_STR.obj \
|
||||
$(WINFE)/MKTEMP.obj \
|
||||
$(NULL)
|
||||
|
||||
SEC_LIBS = \
|
||||
$(DIST)/lib/cert$(MOZ_BITS).lib \
|
||||
$(DIST)/lib/crypto$(MOZ_BITS).lib \
|
||||
$(DIST)/lib/hash$(MOZ_BITS).lib \
|
||||
$(DIST)/lib/key$(MOZ_BITS).lib \
|
||||
$(DIST)/lib/pkcs7$(MOZ_BITS).lib \
|
||||
$(DIST)/lib/secmod$(MOZ_BITS).lib \
|
||||
$(DIST)/lib/secutl$(MOZ_BITS).lib \
|
||||
$(DIST)/lib/ssl$(MOZ_BITS).lib \
|
||||
$(NULL)
|
||||
|
||||
LLFLAGS = $(LLFLAGS) \
|
||||
../lib/$(OBJDIR)/sectool$(MOZ_BITS).lib \
|
||||
$(SEC_LIBS) \
|
||||
$(MOZ_LIBS) \
|
||||
$(DEPTH)/nspr/src/$(OBJDIR)/getopt.obj \
|
||||
$(LIBNSPR) \
|
||||
$(NULL)
|
||||
|
||||
|
||||
# awt3240.lib # brpref32.lib # cert32.lib
|
||||
# crypto32.lib # dllcom.lib # editor32.lib
|
||||
# edpref32.lib # edtplug.lib # font.lib
|
||||
# hash32.lib # htmldg32.lib # img32.lib
|
||||
# javart32.lib # jbn3240.lib # jdb3240.lib
|
||||
# jmc.lib # jpeg3240.lib # jpw3240.lib
|
||||
# jrt3240.lib # js3240.lib # jsd3240.lib
|
||||
# key32.lib # libapplet32.lib # libnjs32.lib
|
||||
# libnsc32.lib # libreg32.lib # mm3240.lib
|
||||
# mnpref32.lib # netcst32.lib # nsdlg32.lib
|
||||
# nsldap32.lib # nsldaps32.lib # nsn32.lib
|
||||
# pkcs1232.lib # pkcs732.lib # pr3240.lib
|
||||
# prefui32.lib # prefuuid.lib # secmod32.lib
|
||||
# secnav32.lib # secutl32.lib # softup32.lib
|
||||
# sp3240.lib # ssl32.lib # uni3200.lib
|
||||
# unicvt32.lib # win32md.lib # winfont.lib
|
||||
# xppref32.lib # zlib32.lib
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
INSTALL = $(MAKE_INSTALL)
|
||||
|
||||
objs: $(OBJS)
|
||||
|
||||
$(PROGRAM)::
|
||||
$(INSTALL) $(DIST)/bin/pr3240.dll ./$(OBJDIR)
|
||||
|
||||
programs: $(PROGRAM)
|
||||
|
||||
install:: $(TARGETS)
|
||||
$(INSTALL) $(TARGETS) $(DIST)/bin
|
||||
|
||||
# ALLXPSTR.obj XP_ALLOC.obj XP_HASH.obj XP_RGB.obj XP_WRAP.obj
|
||||
# CXPRINT.obj XP_C.cl XP_LIST.obj XP_SEC.obj netscape.exp
|
||||
# CXPRNDLG.obj XP_CNTXT.obj XP_MD5.obj XP_STR.obj xp.pch
|
||||
# EXPORT.obj XP_CORE.obj XP_MESG.obj XP_THRMO.obj xppref32.dll
|
||||
# XPASSERT.obj XP_ERROR.obj XP_RECT.obj XP_TIME.obj
|
||||
# XPLOCALE.obj XP_FILE.obj XP_REG.obj XP_TRACE.obj
|
||||
|
||||
|
||||
symbols:
|
||||
@echo "CSRCS = $(CSRCS)"
|
||||
@echo "INCS = $(INCS)"
|
||||
@echo "OBJS = $(OBJS)"
|
||||
@echo "LIBRARY = $(LIBRARY)"
|
||||
@echo "PROGRAM = $(PROGRAM)"
|
||||
@echo "TARGETS = $(TARGETS)"
|
||||
@echo "DIST = $(DIST)"
|
||||
@echo "VERSION_NUMBER = $(VERSION_NUMBER)"
|
||||
@echo "WINFE = $(WINFE)"
|
||||
@echo "DBM_LIB = $(DBM_LIB)"
|
||||
@echo "INSTALL = $(INSTALL)"
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
|
||||
CORE_DEPTH = ../../..
|
||||
|
||||
# MODULE public and private header directories are implicitly REQUIRED.
|
||||
MODULE = nss
|
||||
|
||||
# This next line is used by .mk files
|
||||
# and gets translated into $LINCS in manifest.mnw
|
||||
# The MODULE is always implicitly required.
|
||||
# Listing it here in REQUIRES makes it appear twice in the cc command line.
|
||||
REQUIRES = nspr seccmd
|
||||
|
||||
CSRCS = atob.c
|
||||
|
||||
PROGRAM = atob
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
|
||||
#######################################################################
|
||||
# (1) Include initial platform-independent assignments (MANDATORY). #
|
||||
#######################################################################
|
||||
|
||||
include manifest.mn
|
||||
#MKPROG = purify -cache-dir=/u/mcgreer/pcache -best-effort \
|
||||
# -always-use-cache-dir $(CC)
|
||||
|
||||
#######################################################################
|
||||
# (2) Include "global" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/config.mk
|
||||
|
||||
#######################################################################
|
||||
# (3) Include "component" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
include ../platlibs.mk
|
||||
|
||||
#EXTRA_SHARED_LIBS += \
|
||||
# -L/usr/lib \
|
||||
# -lposix4 \
|
||||
# $(NULL)
|
||||
|
||||
#######################################################################
|
||||
# (5) Execute "global" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/rules.mk
|
||||
|
||||
#######################################################################
|
||||
# (6) Execute "component" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (7) Execute "local" rules. (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
include ../platrules.mk
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,54 +0,0 @@
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
CORE_DEPTH = ../../..
|
||||
|
||||
MODULE = security
|
||||
|
||||
REQUIRES = seccmd dbm
|
||||
|
||||
INCLUDES += -I$(CORE_DEPTH)/nss/lib/softoken
|
||||
|
||||
PROGRAM = bltest
|
||||
|
||||
USE_STATIC_LIBS = 1
|
||||
|
||||
EXPORTS = \
|
||||
$(NULL)
|
||||
|
||||
PRIVATE_EXPORTS = \
|
||||
$(NULL)
|
||||
|
||||
CSRCS = \
|
||||
blapitest.c \
|
||||
$(NULL)
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
This directory contains a set of tests for each cipher supported by BLAPI. Each subdirectory contains known plaintext and ciphertext pairs (and keys and/or iv's if needed). The tests can be run as a full set with:
|
||||
bltest -T
|
||||
or as subsets, for example:
|
||||
bltest -T des_ecb rc2 rsa
|
||||
|
||||
In each subdirectory, the plaintext, key, and iv are ascii, and treated as such. The ciphertext is base64-encoded to avoid the hassle of binary files.
|
||||
|
||||
To add a test, incremement the value in the numtests file. Create a plaintext, key, and iv file, such that the name of the file is incrememted one from the last set of tests. For example, if you are adding the second test, put your data in files named plaintext1, key1, and iv1 (ignoring key and iv if they are not needed, of course). Make sure your key and iv are the correct number of bytes for your cipher (a trailing \n is okay, but any other trailing bytes will be used!). Once you have your input data, create output data by running bltest on a trusted implementation. For example, for a new DES ECB test, run
|
||||
bltest -E -m des_ecb -i plaintext1 -k key1 -o ciphertext1 -a
|
||||
in the tests/des_ecb directory. Then run
|
||||
bltest -T des_ecb
|
||||
from the cmd/bltest directory in the tree of the implementation you want to test.
|
||||
|
||||
Note that the -a option above is important, it tells bltest to expect the input to be straight ASCII, and not base64 encoded binary!
|
||||
|
||||
Special cases:
|
||||
|
||||
RC5:
|
||||
RC5 can take additional parameters, the number of rounds to perform and the wordsize to use. The number of rounds is between is between 0 and 255, and the wordsize is either is either 16, 32, or 64 bits (at this time only 32-bit is supported). These parameters are specified in a paramsN file, where N is an index as above. The format of the file is "rounds=R\nwordsize=W\n".
|
||||
|
||||
public key modes (RSA and DSA):
|
||||
Asymmetric key ciphers use keys with special properties, so creating a key file with "Mozilla!" in it will not get you very far! To create a public key, run bltest with the plaintext you want to encrypt, using a trusted implementation. bltest will generate a key and store it in "tmp.key", rename that file to keyN. For example:
|
||||
bltest -E -m rsa -i plaintext0 -o ciphertext0 -e 65537 -g 32 -a
|
||||
mv tmp.key key0
|
||||
|
||||
[note: specifying a keysize (-g) when using RSA is important!]
|
||||
@@ -1 +0,0 @@
|
||||
oJLgOzZ1GiWt3DGo2sPKaA==
|
||||
@@ -1 +0,0 @@
|
||||
qwertyuiopasdfgh
|
||||
@@ -1 +0,0 @@
|
||||
fedcba9876543210
|
||||
@@ -1 +0,0 @@
|
||||
1
|
||||
@@ -1 +0,0 @@
|
||||
0123456789abcdef
|
||||
@@ -1 +0,0 @@
|
||||
PVuaCIiaKQhblgFCbVMTTg==
|
||||
@@ -1 +0,0 @@
|
||||
fedcba9876543210
|
||||
@@ -1 +0,0 @@
|
||||
1
|
||||
@@ -1 +0,0 @@
|
||||
0123456789abcdef
|
||||
@@ -1 +0,0 @@
|
||||
KV3MDNGKWOc=
|
||||
@@ -1 +0,0 @@
|
||||
12345678
|
||||
@@ -1 +0,0 @@
|
||||
abcdefghijklmnopqrstuvwx
|
||||
@@ -1 +0,0 @@
|
||||
1
|
||||
@@ -1 +0,0 @@
|
||||
Mozilla!
|
||||
@@ -1 +0,0 @@
|
||||
RgckVNh4QcM=
|
||||
@@ -1 +0,0 @@
|
||||
abcdefghijklmnopqrstuvwx
|
||||
@@ -1 +0,0 @@
|
||||
1
|
||||
@@ -1 +0,0 @@
|
||||
Mozilla!
|
||||
@@ -1 +0,0 @@
|
||||
Perdg9FMYQ4=
|
||||
@@ -1 +0,0 @@
|
||||
12345678
|
||||
@@ -1 +0,0 @@
|
||||
zyxwvuts
|
||||
@@ -1 +0,0 @@
|
||||
1
|
||||
@@ -1 +0,0 @@
|
||||
Mozilla!
|
||||
@@ -1 +0,0 @@
|
||||
3bNoWzzNiFc=
|
||||
@@ -1 +0,0 @@
|
||||
zyxwvuts
|
||||
@@ -1 +0,0 @@
|
||||
1
|
||||
@@ -1 +0,0 @@
|
||||
Mozilla!
|
||||
@@ -1 +0,0 @@
|
||||
fB0bnKWvjT6X5NIkZ5l/Y/DXZ6QNI6j0iPhR/ZERkfj67xRnTWY1cg==
|
||||
@@ -1,6 +0,0 @@
|
||||
AAAAQI3ypJRJInaqPSV1m7BoacvqwNg6+40M98u4Mk8NeILl0HYvxbchDq/C6a2s
|
||||
Mqt6rElpPfv4NyTC7Ac27jHIApEAAAAUx3MhjHN+yO6ZO08t7TD0jtrOkV8AAABA
|
||||
Ym0CeDnqChNBMWOlW0y1ACmdVSKVbO/LO/8Q85nOLC5xy53l+iS6v1jlt5Uhklyc
|
||||
xC6fb0ZLCIzFcq9T5teIAgAAAEAZExhx11sWEqgZ8p140bDXNG96p3u2KoWb/WxW
|
||||
ddqdIS06Nu8Wcu9mC4x8JVzA7HSFj7oz9EwGaZYwp2sDDuMzAAAAFCBwsyI9ujcv
|
||||
3hwP/HsuO0mLJgYU
|
||||
@@ -1 +0,0 @@
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAA=
|
||||
@@ -1 +0,0 @@
|
||||
1
|
||||
@@ -1 +0,0 @@
|
||||
qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
|
||||
@@ -1,4 +0,0 @@
|
||||
AAAAQI3ypJRJInaqPSV1m7BoacvqwNg6+40M98u4Mk8NeILl0HYvxbchDq/C6a2s
|
||||
Mqt6rElpPfv4NyTC7Ac27jHIApEAAAAUx3MhjHN+yO6ZO08t7TD0jtrOkV8AAABA
|
||||
Ym0CeDnqChNBMWOlW0y1ACmdVSKVbO/LO/8Q85nOLC5xy53l+iS6v1jlt5Uhklyc
|
||||
xC6fb0ZLCIzFcq9T5teIAg==
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user