-
Notifications
You must be signed in to change notification settings - Fork 18
Home
Анализатор разрабатывается на языке программирования С++11, использование более новых стандартов в данный момент не допускается. Все комментарии, размещенные в коде и сопровождающие фиксации в репозитории должны быть написаны на английском языке. Комментарии к фиксациям должны начинаться с маркера, обозначающего принадлежность загружаемых изменений, например, [TSAR] или [TSAR-cmake] для анализатора и [BASE] для изменений связанных с базовыми конструкциями (Base Construction Library (BCL)).
Все конструкции относящиеся к TSAR должны располагаться в пространстве имен tsar
, детали реализации можно скрыть в пространстве имен detail
. Если создаются конструкции относящиеся к LLVM, например проходы анализа и преобразований, то они должны располагаться в пространстве имен llvm
.
При разработке применяется Google C++ Style Guide в комбинации c LLVM Coding Standards и некоторыми модификациями. Основные правила приведены ниже.
Документацию по языку С++ можно найти в следующих источниках:
- С++ Wiki ,также доступная на русском языке, но чуть менее полная.
- Стандартные библиотеки и язык C++ - документация в Microsoft MSDN.
- C++ 11 FAQ от Бьярна Страуструпа - краткое описание (на русском языке) возможностей, добавленных в стандарте С++ 11.
- Описание стандарта С++ на английском языке.
- Бьерн Страуструп. Программирование. Принципы и практика с использованием C++ (обновлено для С++11/С++14) // 2-е издание. Изд-во: Вильямс, 2016. 1328 с.
- Скотт Мейерс. Эффективное использование C++. 55 верных советов улучшить структуру и код ваших программ // 3-е издание. Изд-во: ДМК Пресс, 2014. 300 с.
- Скотт Мейерс. Эффективный и современный С++. 42 рекомендации по использованию C++11 и C++14 // Изд-во: Вильямс, 2015. 304 с.
Полезная информация по LLVM может быть получена с сайта http://llvm.org:
- Описание LLVM IR
- Полезные базовые конструкции LLVM
- Введение в разработку проходов анализа и преобразований
- Создание новых опций командной строки для инструмента
- Введение в представление отладочной информации в LLVM IR
- Doxygen-документация по LLVM
- Преобразование типов в стиле LLVM
- и др.
Допускается длина строки не более 80 символов. Исключение делается только для строковых констант, не умещающихся в данный предел. Использование символа табуляции в коде не допускается, данные символы должны быть заменены на пробелы (автоматическая замена поддерживается в большинстве средств разработки). Стандартный размер отступа - 2 символа, все завершающие пробельные символы должны удаляться.
Допускается два вида комментариев:
// Обычный комментарий
/// \brief Документирующий комментарий оформляется в формате
/// Doxygen-комментария (http://www.doxygen.org/).
///
/// Документирующие Doxygen-комментарии должны быть написаны для всех открытых
/// методов, членов, типов класса, всех доступных извне элементов (в том числе
/// классов, пространств имен, типов (typedef)).
/// \note Рекомендуется указывать комментарии и для остальных объектов.
В начале каждого файла должен содержаться блок комментариев кратко описывающий содержимое файла.
//===--- tsar_private.h - Private Variable Analyzer -------------*- C++ -*-===//
//
// Traits Static Analyzer (SAPFOR)
//
//===----------------------------------------------------------------------===//
//
// This file defines passes to determine locations which can be privatized.
// We use data-flow framework to implement this kind of analysis. This file
// contains elements which is necessary to determine this framework.
// The following articles can be helpful to understand it:
// * "Automatic Array Privatization" Peng Tu and David Padua
// * "Array Privatization for Parallel Execution of Loops" Zhiyuan Li.
//
//===----------------------------------------------------------------------===//
Перед объектами, расположенными в пространстве имен отступы не ставятся:
namespace tsar {
/// Color of a node which depth-first search (DFS) has visited.
enum DFSColor {
...
После заголовка функции, ключевого слова template
, специализируемого класса или функции отступы не ставятся.
/// \brief Returns true if the specified directed graph is acyclic.
///
/// \param [in] G Directed graph, it can not be null.
/// \pre The llvm::GraphTraits class should be specialized by GraphType.
/// Note that GraphType is generally a pointer type, for example BasicBlock *.
template<class GraphType> inline bool isDAG(GraphType G) {
return !findBackEdge<GraphType>(G).first;
}
Отступы ставятся после ключевых слов if
, for
, while
и аналогичных.
Если параметры функции не умещаются в границы 80 символов, то перед ними ставится отступ 4 символа.
template<class location_iterator, class ResultSet>
static void difference(
const location_iterator &LocBegin, const location_iterator &LocEnd,
const LocationSet &LocSet, ResultSet &Result) {
if (LocSet.mLocations.empty())
...
Открывающая фигурная скобка размещается на той же строке что и предшествующая ей конструкция. Ключевое слово else
размещается на той же строке, что и предшествующая закрывающая фигурная скобка. Если в блоке if-then-else
хотя бы один раз встречаются фигурные скобки, то фигурные скобки должны стоят во всех ветках. *Строки идут подряд без пропусков за исключением отступов перед введением новых классов, типов, функций, блока конструкций using
и #include
.
if (SToNode == Blocks.end()) {
BBToN.second->addSuccessor(ExitNode);
ExitNode->addPredecessor(BBToN.second);
} else if (*SI == LT::getHeader(L)) {
...
} else if (SToNode->second != BBToN.second) {
BBToN.second->addSuccessor(SToNode->second);
}
Имена классов и типов должны начинаться с заглавной буквы. Имена функций начинаются со строчной буквы. Использование нижнего подчеркивания _
и строчных букв в именах классов и типов допускается только для stl-подобных конструкций.
...
/// This type used to iterate over all nodes in the region body.
typedef std::vector<DFNode *>::const_iterator node_iterator;
/// This type used to iterate over internal regions.
typedef std::vector<DFRegion *>::const_iterator region_iterator;
...
/// Returns iterator that points to the beginning of the nodes list.
node_iterator node_begin() const { return mNodes.begin(); }
/// Returns iterator that points to the ending of the nodes list.
node_iterator node_end() const { return mNodes.end(); }
...
Имена переменных должны начинаться с заглавной буквы. Для членов класса должен ставиться префикс m
, для глобальных переменных (использование которых не рекомедуется) - префикс g
.
Имена должны быть понятны и точно описывать назначение именуемой сущности. Допускаются общеупотребительные в рамках проекта сокращения имен (BasicBlock - BB, Function - F, Control Flow Graph - CFG и т.д.), или сокращения имен с небольшой областью видимости для более компактного размещения кода.
...
for (auto I = LT::block_begin(L), E = LT::block_end(L); I != E; ++I) {
if (Blocks.count(*I))
continue;
DFBlock *N = new DFBlock(*I);
R->addNode(N);
Blocks.insert(std::make_pair(*I, N));
}
...
Закрытые методы и члены классов должны быть размещены в конце описания класса.
Объявление класса должно начинаться с секции public
, затем следует секция protected
и секция private
.
...
/// Specifies that there are unknown instructions in the node.
///
/// \return False if it has been already specified.
bool addUnknownInst(llvm::Instruction *I) {
assert(I && "Instruction must not be null!");
return mUnknownInsts.insert(I).second;
}
private:
LocationSet mDefs;
LocationSet mMayDefs;
LocationSet mUses;
llvm::AliasSetTracker mExplicitAccesses;
PointerSet mAddressAccesses;
InstructionSet mUnknownInsts;
};
Классы не допускающие копирования должны закрыто наследовать класс bcl::Uncopyable
определенный в файле idb/trunk/src/base/utility.h
namespace llvm {
/// This pass determines locations which can be privatized.
class PrivateRecognitionPass :
public FunctionPass, private bcl::Uncopyable {
...
Для функций должен соблюдаться следующий порядок задания параметров: сначала указываются входные, затем выходные. Не следует добавлять новые параметры функции в конец ее объявления только потому что, они были добавлены последними.
Предпочитайте писать компактные функции. Если функция занимает слишком много строк кода, стоит подумать о том как ее разбить на несколько компактных. Это поможет сделать код более понятным, но не должно нарушать логическую структуру программы. Сопровождать и отлаживать большие функции непросто, особенно когда этим занимаются другие разработчики.
Перечисления должны начинаться со вспомогательного элемента с префиксом FIRST
и заканчиваться тремя вспомогательными элементами с префиксами LAST
, INVALID
, NUMBER
соответственно.
/// Kind of a node.
/// If you add a new kind of region it should be in the range between
/// FIRST_KIND_REGION and LAST_KIND_REGION
enum Kind {
FIRST_KIND = 0,
KIND_BLOCK = FIRST_KIND,
KIND_ENTRY,
KIND_EXIT,
KIND_LATCH,
FIRST_KIND_REGION,
KIND_LOOP = FIRST_KIND_REGION,
KIND_FUNCTION,
LAST_KIND_REGION = KIND_FUNCTION,
LAST_KIND = LAST_KIND_REGION,
INVALID_KIND,
NUMBER_KIND = INVALID_KIND,
};
Для сокращения количества ошибок в коде и времени затраченного на их поиск рекомендуется использовать конструкции assert
. Для точного описания проверяемого утверждения следует использовать строковую константу:
assert(*I == GT::getEntryNode(DFG) &&
"The first node in the topological order differs from the entry node in the data-flow framework!");
В данном случае аварийный останов программы произойдет, если условие *I == GT::getEntryNode(DFG)
окажется ложно. При этом текстовое сообщение, описывающее проверяемое утверждение, не влияет на выполнение проверки и используется в пояснительных целях.
Конструкции assert
могут быть удалены на этапе компиляции и не должны менять поведение программы. После их отключения программа должна оставаться корректной. Следовательно, внутри данных конструкций нельзя изменять переменные программы, используемые не только с целью отладки, вызывать функции, изменяющие состояние программы.
Для проверки утверждений на этапе компиляции могут использоваться конструкции static_assert
:
static_assert(!IsCellExist<CellNext, CellKey>::value,
"Each cell must be presented only once in the map!");
Написать нам можно через форму связи на сайте проекта DVM-системы.