No OneTemporary

File Metadata

Created
Sat, Mar 14, 4:39 AM
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/.gitignore b/.gitignore
index d6ce9c6..59de723 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,82 +1,84 @@
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Compiled Dynamic libraries
*.so
*.so.*
*.dylib
*.dll
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
*.class
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
# Qt-es
/.qmake.cache
/.qmake.stash
*.pro.user
*.pro.user.*
*.moc
moc_*.cpp
qrc_*.cpp
ui_*.h
Makefile*
*-build-*
# QtCreator
*.autosave
coco/*.old
coco/*~
*~
cpp/build-*/*
cpp/xreate-debug/*
cpp/xreate-release/*
cpp/.idea
CMakeLists.txt.user
cmake_install.cmake
project/*
nb*.xml
.*
target/*
/tools/phabricator/xreate-frontend/nbproject/private/
documentation/trash4/
trash/
CMakeFiles/
gen-cpp/
generated-cpp/
gen-php/
generated-js/
books/
build/
coco/Parser.*
coco/Scanner.*
tools/phabricator/administration/
scripts/**/tmp-*
+cpp/tests/vendorsAPI/
+
diff --git a/config/default.json b/config/default.json
index a6f1199..3a6cf8e 100644
--- a/config/default.json
+++ b/config/default.json
@@ -1,73 +1,73 @@
{
"containers": {
"id": {
"implementations": "impl_fulfill_cluster",
"clusters": "var_cluster",
"prototypes": "proto_cluster",
"linkedlist": "linkedlist"
},
"impl": {
"solid": "solid",
"onthefly": "on_the_fly"
}
},
"logging": {
"id": "logging"
},
"function-entry": "entry",
- "clasp": {
+ "transcend": {
"bindings" : {
"variable": "bind",
"function": "bind_func",
"scope": "bind_scope",
"function_demand" : "bind_function_demand",
"scope_decision": "bind_scope_decision"
},
"context" : {
"decisions":{
"dependent": "resolution_dependency"
}
},
"nonevalue": "nonevalue",
"ret": {
"symbol": "retv",
"tag": "ret"
}
},
"tests": {
- "template": "polymorphs",
+ "template": "latereasoning",
"templates": {
- "current-fix":"*",
+ "current-fix":"Compilation.*-Compilation.Sequence1:Compilation.full_IFStatementWithVariantType",
"default": "*-Adhoc.*:Containers.*:Compilation.full_IFStatementWithVariantType:Types.full_VariantType_Switch1:Context.full_LateContext:Context.pathDependentContext:CFA.testLoopContextExists",
"ast": "AST.*",
"effects": "Effects.*",
"basic": "Attachments.*",
"compilation": "Compilation.*-Compilation.full_IFStatementWithVariantType",
"communication": "Communication.*",
"cfa": "CFA.*",
"containers": "Containers.*",
"dfa": "DFA.*",
"diagnostic": "Diagnostic.*",
"dsl": "Association.*:Interpretation.*",
"exploitation": "Exploitation.*",
"ExpressionSerializer": "ExpressionSerializer.*",
"externc": "InterfaceExternC.*",
"loops": "Loop.*",
- "latereasoning": "LateReasoning.*",
+ "latereasoning": "LateReasoning.Syntax1",
"modules": "Modules.*",
"polymorphs": "Polymorphs.*",
"types": "Types.*",
"virtualization": "Virtualization.test2",
"vendorsAPI/clang": "ClangAPI.*",
"vendorsAPI/xml2": "libxml2*"
}
}
}
diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt
index 03464bf..c87e905 100644
--- a/cpp/src/CMakeLists.txt
+++ b/cpp/src/CMakeLists.txt
@@ -1,227 +1,230 @@
cmake_minimum_required(VERSION 2.8.11)
project(xreate)
cmake_policy(SET CMP0022 NEW)
message("MODULES" ${CMAKE_MODULE_PATH})
# LLVM
#======================
FIND_PACKAGE (LLVM REQUIRED)
set(LLVM_VERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR})
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message("LLVM LIB PATH:" ${LLVM_LIBRARY_DIRS})
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
INCLUDE_DIRECTORIES(${LLVM_INCLUDE_DIRS})
message(STATUS "INCLUDE DIR: ${LLVM_INCLUDE_DIRS}")
add_definitions(${LLVM_DEFINITIONS})
-message("LLVM DEFS: " ${LLVM_DEFINITIONS})
-
-llvm_map_components_to_libnames(LLVM_LIBS core nativecodegen native executionengine mcjit support option)
-message("LLVM LIBS: " ${LLVM_LIBS})
+message(STATUS "LLVM DEFS: " ${LLVM_DEFINITIONS})
+execute_process(
+ COMMAND llvm-config --libs
+ OUTPUT_VARIABLE LLVM_LIBS
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+message(STATUS "LLVM LIBS: " ${LLVM_LIBS})
# CLANG
#======================
set(CLANG_LIBS
clangCodeGen
clangASTMatchers
clangQuery
clangTooling
clangFrontend
clangSerialization
clangDriver
clangParse
clangSema
clangAnalysis
clangAST
clangEdit
clangLex
clangBasic
)
# POTASSCO
#======================
set(POTASSCO_PATH "/opt/potassco/clingo" CACHE PATH "Path to potassco sources")
set(POTASSCO_INCLUDE_PATH
${POTASSCO_PATH}/libgringo
${POTASSCO_PATH}/libclasp
${POTASSCO_PATH}/libclingo
${POTASSCO_PATH}/libprogram_opts
${POTASSCO_PATH}/liblp
)
INCLUDE_DIRECTORIES(${POTASSCO_INCLUDE_PATH})
set(LIBCLASP_LIBS
clingo
clasp
gringo
program_opts
reify
lp
)
message("CLASP LIBS: " ${LIBCLASP_LIBS})
# OTHER DEPENDENCIES
#===========================
set(JEAYESON_INCLUDE_PATH
${CMAKE_HOME_DIRECTORY}/../vendors/jeayeson/include/
)
INCLUDE_DIRECTORIES(${JEAYESON_INCLUDE_PATH})
# COCO
#===========================
set(COCO_EXECUTABLE "" CACHE PATH "Path to coco executable")
set(COCO_FRAMES_PATH "" CACHE PATH "Path to coco frames")
set(COCO_GRAMMAR_PATH ${CMAKE_HOME_DIRECTORY}/../grammar/)
set(COCO_SOURCE_FILES_MAIN
${COCO_GRAMMAR_PATH}/main/Parser.cpp
${COCO_GRAMMAR_PATH}/main/Scanner.cpp
)
set(COCO_SOURCE_FILES_MODULES
${COCO_GRAMMAR_PATH}/modules/Parser.cpp
${COCO_GRAMMAR_PATH}/modules/Scanner.cpp
)
set(COCO_SOURCE_FILES ${COCO_SOURCE_FILES_MODULES} ${COCO_SOURCE_FILES_MAIN})
INCLUDE_DIRECTORIES(${COCO_GRAMMAR_PATH})
add_custom_command(OUTPUT ${COCO_SOURCE_FILES_MAIN}
COMMAND ${COCO_GRAMMAR_PATH}/gen-grammar main ${COCO_EXECUTABLE} ${COCO_FRAMES_PATH}
WORKING_DIRECTORY ${COCO_GRAMMAR_PATH}
MAIN_DEPENDENCY ${COCO_GRAMMAR_PATH}/xreate.ATG
)
add_custom_command(OUTPUT ${COCO_SOURCE_FILES_MODULES}
COMMAND ${COCO_GRAMMAR_PATH}/gen-grammar modules ${COCO_EXECUTABLE} ${COCO_FRAMES_PATH}
WORKING_DIRECTORY ${COCO_GRAMMAR_PATH}
MAIN_DEPENDENCY ${COCO_GRAMMAR_PATH}/modules.ATG
)
message(STATUS "COCO GRAMMAR BUILD STATUS:" ${COCO_OUTPUT})
# XREATE
#======================
set(SOURCE_FILES
+ analysis/DominatorsTreeAnalysisProvider.cpp
+ llvmlayer.cpp
+ ExternLayer.cpp
+ compilation/latereasoning.cpp
+ pass/compilepass.cpp
query/polymorph.cpp
- clasplayer.cpp
+ transcendlayer.cpp
analysis/utils.cpp
analysis/dfagraph.cpp
pass/dfapass.cpp
compilation/targetinterpretation.cpp
pass/interpretationpass.cpp
ast.cpp
xreatemanager.cpp
analysis/typeinference.cpp
aux/xreatemanager-decorators.cpp
compilation/operators.cpp
compilation/transformations.cpp
compilation/transformersaturation.cpp
- pass/compilepass.cpp
pass/versionspass.cpp
attachments.cpp
- ExternLayer.cpp
analysis/cfagraph.cpp
compilation/containers.cpp
compilation/advancedinstructions.cpp
- llvmlayer.cpp
utils.cpp
pass/abstractpass.cpp
pass/cfapass.cpp
contextrule.cpp
query/containers.cpp
- analysis/DominatorsTreeAnalysisProvider.cpp
aux/serialization/expressionserializer.cpp
modules.cpp
)
set(XREATE_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/
)
INCLUDE_DIRECTORIES(${XREATE_INCLUDE_DIRS})
set(XREATE_PRIVATE_INCLUDE_DIRS
${XREATE_INCLUDE_DIRS}
${COCO_GRAMMAR_PATH}
${JEAYESON_INCLUDE_PATH}
${LLVM_INCLUDE_DIRS}
${POTASSCO_INCLUDE_PATH}
)
add_library(${PROJECT_NAME} SHARED ${COCO_SOURCE_FILES} ${SOURCE_FILES})
target_link_libraries(${PROJECT_NAME})
target_include_directories(${PROJECT_NAME} INTERFACE
${XREATE_INCLUDE_DIRS}
${COCO_GRAMMAR_PATH}
${JEAYESON_INCLUDE_PATH}
${LLVM_INCLUDE_DIRS}
${POTASSCO_INCLUDE_PATH}
)
get_directory_property(DEFINITIONS_ALL DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_DEFINITIONS)
message("definitions all: " ${DEFINITIONS_ALL})
target_compile_definitions(${PROJECT_NAME} INTERFACE ${DEFINITIONS_ALL})
get_directory_property(COMPILATION_OPTIONS_ALL DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_OPTIONS)
message("compilations all: " ${COMPILATION_OPTIONS_ALL})
target_compile_options(${PROJECT_NAME} INTERFACE ${COMPILATION_OPTIONS_ALL})
SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY
INTERFACE_LINK_LIBRARIES ${LIBCLASP_LIBS} ${CLANG_LIBS} ${LLVM_LIBS} tbb boost_system boost_filesystem
)
#${CLANG_LIBS}
#set (LINK_INTERFACE_LIBRARIES "")
# FUNCTION(PREPEND var prefix)
# SET(listVar "")
# FOREACH(f ${ARGN})
# LIST(APPEND listVar "${prefix}/${f}")
# ENDFOREACH(f)
# SET(${var} "${listVar}" PARENT_SCOPE)
# ENDFUNCTION(PREPEND)
#set(COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "-j4")
#cotire(xreate)
# MACRO (ADD_PCH_RULE _header_filename _src_list)
# SET(_gch_filename "${_header_filename}.gch")
# LIST(APPEND ${_src_list} ${_gch_filename})
# SET (_args ${CMAKE_CXX_FLAGS})
# LIST(APPEND _args -c ${_header_filename} -o ${_gch_filename})
# GET_DIRECTORY_PROPERTY(DIRINC INCLUDE_DIRECTORIES)
# foreach (_inc ${DIRINC})
# LIST(APPEND _args "-I" ${_inc})
# endforeach(_inc ${DIRINC})
# SEPARATE_ARGUMENTS(_args)
# add_custom_command(OUTPUT ${_gch_filename}
# COMMAND rm -f ${_gch_filename}
# COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} ${_args}
# DEPENDS ${_header_filename})
# ENDMACRO(ADD_PCH_RULE _header_filename _src_list)
# ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/ast.h SOURCE_FILES)
# ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/llvmlayer.h SOURCE_FILES)
# ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/clasplayer.h SOURCE_FILES)
# ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/pass/abstractpass.h SOURCE_FILES)
diff --git a/cpp/src/ExternLayer.cpp b/cpp/src/ExternLayer.cpp
index 6ede88c..02bdedb 100644
--- a/cpp/src/ExternLayer.cpp
+++ b/cpp/src/ExternLayer.cpp
@@ -1,325 +1,318 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ExternLayer.cpp
*
* Created on: 4/21/15
* Author: pgess <v.melnychenko@xreate.org>
- */
-
-/**
+ *
* \file ExternLayer.h
* \brief Support of external C code. Wrapper over Clang
*/
-//
-// Created by pgess on .
-//
-
#include "ExternLayer.h"
-
-#include <cstdio>
-#include <iostream>
#include "clang/Tooling/Tooling.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/PreprocessorOptions.h"
+#include "clang/CodeGen/ModuleBuilder.h"
+#include "clang/CodeGen/CodeGenABITypes.h"
#include <llvm/Support/DynamicLibrary.h>
#include <boost/format.hpp>
#include <boost/algorithm/string/join.hpp>
-
-#include "../../vendors/clang-codegen-private-3.8/CodeGenModule.h"
+#include <cstdio>
+#include <iostream>
using namespace std;
using namespace clang;
using namespace clang::driver;
using namespace clang::tooling;
using namespace clang::ast_matchers;
using namespace llvm;
namespace xreate {
class FinderCallbackTypeDecl : public MatchFinder::MatchCallback {
public :
QualType typeResult;
virtual void run(const MatchFinder::MatchResult &Result) {
if (const TypedefDecl* decl = Result.Nodes.getNodeAs<clang::TypedefDecl>("typename")) {
typeResult = decl->getUnderlyingType();
}
}
};
class FinderCallbackFunction : public MatchFinder::MatchCallback {
public :
QualType typeResult;
virtual void run(const MatchFinder::MatchResult &Result) {
if (const FunctionDecl* decl = Result.Nodes.getNodeAs<clang::FunctionDecl>("function")) {
typeResult = decl->getType();
}
}
};
void
ExternData::addLibrary(Atom<Identifier_t>&& name, Atom<String_t>&& package)
{
__dictLibraries.emplace(name.get(), package.get());
}
void
ExternData::addIncludeDecl(Expression&& e)
{
assert(e.op == Operator::LIST_NAMED);
//TODO ?? implement Expression parsing(Array of Expr as vector<string>);
for(size_t i=0, size=e.operands.size(); i<size; ++i)
{
std::string library = e.bindings.at(i);
assert(__dictLibraries.count(library));
std::string package = __dictLibraries.at(library);
Expression listHeaders = e.operands.at(i);
assert(listHeaders.op == Operator::LIST);
std::vector<std::string> headers;
std::transform(listHeaders.operands.begin(), listHeaders.operands.end(), std::inserter(headers, headers.end()),
[](const Expression& o){
assert(o.__state == Expression::STRING);
return o.getValueString();
});
entries.emplace_back(ExternEntry{package, std::move(headers)});
}
}
void
ExternLayer::addExternalData(const std::vector<ExternEntry>& data){
entries.insert(entries.end(), data.begin(), data.end());
}
ExternLayer::ExternLayer(LLVMLayer *llvm)
: __llvm(llvm)
{}
std::vector<string>
ExternLayer::fetchPackageFlags(const ExternEntry& entry){
std::vector<string> args;
FILE* flags = popen((string("pkg-config --cflags ") + entry.package).c_str(), "r");
size_t linesize=0;
char* linebuf=0;
ssize_t linelen=0;
while ((linelen=getdelim(&linebuf, &linesize, ' ', flags))>0) {
if (linebuf[0]=='\n') continue;
if (linelen==1 && linebuf[0]==' ') continue;
//cut unwanted symbols at the end
char symbLast = linebuf[linelen-1 ];
if (symbLast == ' ' || symbLast == '\n') linebuf[linelen-1] = 0;
//print header for debug purposes
llvm::outs() << '<' << linebuf << "> ";
args.push_back(linebuf);
free(linebuf);
linebuf = 0;
}
pclose(flags);
return (args);
}
std::vector<string>
ExternLayer::fetchPackageLibs(const ExternEntry& entry){
std::vector<string> libs;
FILE* flags = popen((string("pkg-config --libs ") + entry.package).c_str(), "r");
size_t linesize=0;
char* linebuf=0;
ssize_t linelen=0;
while ((linelen=getdelim(&linebuf, &linesize, ' ', flags))>0) {
if (linebuf[0]=='\n') continue;
if (linelen==1 && linebuf[0]==' ') continue;
//cut unwanted symbols at the end
char symbLast = linebuf[linelen-1 ];
if (symbLast == ' ' || symbLast == '\n') linebuf[linelen-1] = 0;
//cut unwanted symbols at the beginning
if (linelen>1 && linebuf[0] == '-' && linebuf[1] == 'l'){
libs.push_back(linebuf + 2);
} else {
libs.push_back(linebuf);
}
//print lib name for debug purposes
llvm::outs() << '<' << linebuf << "> ";
free(linebuf);
linebuf = 0;
}
pclose(flags);
return (libs);
}
void
ExternLayer::loadLibraries(vector<string>&& libs){
string msgErr;
for (const string& lib: libs) {
const string& libName = string("lib")+lib+".so";
if (!llvm::sys::DynamicLibrary::LoadLibraryPermanently(libName.c_str(), &msgErr)){
llvm::errs()<<"\n"<<"Loading library "<<lib<<". " <<msgErr<<"\n";
}
}
}
void
ExternLayer::init(const AST* root) {
addExternalData(root->__externdata);
// TODO -EXTERN01.DIP, use default include path from 'clang -xc++ -E'
list<string> code;
std::vector<string> args{
"-I/usr/include"
,"-I/usr/local/include"
- ,"-I/usr/lib/llvm-3.6/lib/clang/3.6.2/include"
+ ,"-I/usr/lib64/clang/5.0.1/include"
// ,"-I/usr/lib/gcc/x86_64-linux-gnu/4.9/include"
// ,"-I/usr/include/x86_64-linux-gnu"
};
std::vector<string> libs;
boost::format formatInclude("#include \"%1%\"");
for(const ExternEntry& entry: entries)
{
llvm::outs()<<"[ExternC] Processing package: "<< entry.package << "\n";
llvm::outs()<<"[ExternC] args: ";
vector<string>&& args2 = fetchPackageFlags(entry);
args.insert(args.end(), args2.begin(), args2.end());
for(const string arg: args2) {
llvm::outs()<< "<" << arg << "> ";
}
llvm::outs()<<"\n[ExternC] libs: ";
args2 = fetchPackageLibs(entry);
for(const string arg: args2) {
llvm::outs()<< "<" << arg << "> ";
}
libs.insert(libs.end(), args2.begin(), args2.end());
llvm::outs()<<"\n[ExternC] headers: ";
std::transform(entry.headers.begin(), entry.headers.end(), std::inserter(code, code.begin()),
[&formatInclude](const string header ) {
string line = boost::str(formatInclude % header);
llvm::outs()<< "<" << line << "> ";
return line;
});
llvm::outs() << '\n';
}
loadLibraries(move(libs));
ast = buildASTFromCodeWithArgs(boost::algorithm::join(code, "\n"), args);
- __cgo.reset(new CodeGenOptions);
- __llvm->module->setDataLayout(ast->getASTContext().getTargetInfo().getDataLayoutString());
-
- std::unique_ptr<clang::HeaderSearchOptions> __hso(new HeaderSearchOptions());
- std::unique_ptr<clang::PreprocessorOptions> __ppo(new PreprocessorOptions());
-
- __cgm.reset(new CodeGen::CodeGenModule(
- ast->getASTContext(),
-
- *__hso,
- *__ppo,
- *__cgo,
- *__llvm->module,
- ast->getASTContext().getDiagnostics()));
+ __llvm->module->setDataLayout(ast->getASTContext().getTargetInfo().getDataLayout());
+
+ __codegen.reset(CreateLLVMCodeGen(
+ ast->getASTContext().getDiagnostics(),
+ __llvm->module->getName(),
+ HeaderSearchOptions(),
+ PreprocessorOptions(),
+ CodeGenOptions(),
+ __llvm->llvmContext
+ ));
};
bool
ExternLayer::isPointer(const clang::QualType &t) {
const clang::Type * tInfo = t.getTypePtr();
assert(tInfo);
return tInfo->isAnyPointerType();
}
llvm::Type*
ExternLayer::toLLVMType(const clang::QualType& t){
- return __cgm->getTypes().ConvertType(t);
+ return CodeGen::convertTypeForMemory( __codegen->CGM(), t);
}
std::vector<std::string>
ExternLayer::getStructFields(const clang::QualType& ty)
{
clang::QualType t = ty;
if (isPointer(ty)){
const clang::PointerType* tPtr = ty->getAs<clang::PointerType>();
t = tPtr->getPointeeType();
}
assert(t.getTypePtr()->isRecordType());
const RecordType *record = t->getAsStructureType();
assert(record);
std::vector<std::string> result;
//FieldDecl* field: record->getDecl()->fields()
for (auto i=record->getDecl()->field_begin(); i!= record->getDecl()->field_end(); ++i){
result.push_back(i->getName());
}
return result;
}
clang::QualType
ExternLayer::lookupType(const std::string& id){
MatchFinder finder;
FinderCallbackTypeDecl callbackTypeDecl;
auto matcherTypeDecl = typedefDecl(hasName(id)).bind("typename");
finder.addMatcher(matcherTypeDecl, &callbackTypeDecl);
finder.matchAST(ast->getASTContext());
assert(! callbackTypeDecl.typeResult.isNull());
return callbackTypeDecl.typeResult;
}
llvm::Function*
ExternLayer::lookupFunction(const std::string& name){
if (__functions.count(name)){
return __functions.at(name);
}
MatchFinder finder;
FinderCallbackFunction callback;
auto matcher = functionDecl(hasName(name)).bind("function");
finder.addMatcher(matcher, &callback);
finder.matchAST(ast->getASTContext());
if (callback.typeResult.isNull()){
cout <<"[External Layer] " << "Unknown function: "<<name << endl;
assert(false && "Unknown external function");
}
const QualType& tyFuncQual = callback.typeResult;
- llvm::Type *tyRaw = __cgm->getTypes().ConvertType(tyFuncQual);
+ llvm::Type *tyRaw = CodeGen::convertTypeForMemory(__codegen->CGM(), tyFuncQual);
llvm::FunctionType* tyRawFunc = llvm::dyn_cast<llvm::FunctionType>(tyRaw);
- llvm::Function* function = llvm::Function::Create(tyRawFunc, llvm::GlobalValue::ExternalLinkage, name, __llvm->module);
+ llvm::Function* function = llvm::Function::Create(
+ tyRawFunc,
+ llvm::GlobalValue::ExternalLinkage,
+ name,
+ __llvm->module.get());
__functions.emplace(name, function);
return function;
}
}//end of xreate namespace
diff --git a/cpp/src/ExternLayer.h b/cpp/src/ExternLayer.h
index 183b233..fde7e6a 100644
--- a/cpp/src/ExternLayer.h
+++ b/cpp/src/ExternLayer.h
@@ -1,60 +1,63 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ExternLayer.h
*
* Created on: 4/21/15
* Author: pgess <v.melnychenko@xreate.org>
*/
#ifndef XREATE_EXTERNLAYER_H
#define XREATE_EXTERNLAYER_H
#include "llvmlayer.h"
#include <vector>
#include <string>
#include <map>
#include "ast.h"
#include "clang/AST/ASTContext.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/CodeGen/CodeGenABITypes.h"
+namespace clang {
+ class CodeGenerator;
+}
+
namespace xreate {
struct ExternData {
void addLibrary(Atom<Identifier_t>&& name, Atom<String_t>&& package);
void addIncludeDecl(Expression&& e);
std::vector<ExternEntry> entries;
std::map<std::string, std::string> __dictLibraries;
};
class ExternLayer {
public:
ExternLayer(LLVMLayer* llvm);
llvm::Function* lookupFunction(const std::string& name);
clang::QualType lookupType(const std::string& id);
std::vector<std::string> getStructFields(const clang::QualType& ty);
llvm::Type* toLLVMType(const clang::QualType& t);
bool isPointer(const clang::QualType& t);
void init(const AST* root);
static std::vector<std::string> fetchPackageFlags(const ExternEntry& entry);
static std::vector<std::string> fetchPackageLibs(const ExternEntry& entry);
private:
std::unique_ptr<clang::ASTUnit> ast;
- std::unique_ptr<clang::CodeGen::CodeGenModule> __cgm;
- std::unique_ptr<clang::CodeGenOptions> __cgo;
+ std::unique_ptr<clang::CodeGenerator> __codegen;
LLVMLayer* __llvm;
std::vector<ExternEntry> entries;
std::map<std::string, llvm::Function*> __functions;
void addExternalData(const std::vector<ExternEntry>& data);
void loadLibraries(std::vector<std::string>&& libs);
};
}
#endif //XREATE_EXTERNLAYER_H
diff --git a/cpp/src/analysis/DominatorsTreeAnalysisProvider.cpp b/cpp/src/analysis/DominatorsTreeAnalysisProvider.cpp
index cb185db..93d52bd 100644
--- a/cpp/src/analysis/DominatorsTreeAnalysisProvider.cpp
+++ b/cpp/src/analysis/DominatorsTreeAnalysisProvider.cpp
@@ -1,245 +1,275 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: DominatorsTreeAnalysisProvider.cpp
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on May 13, 2016, 11:39 AM
*/
/**
* \file DominatorsTreeAnalysisProvider.h
* \brief Dominators Tree analysis
*/
#include "analysis/cfagraph.h"
#include "analysis/DominatorsTreeAnalysisProvider.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/Support/GenericDomTreeConstruction.h"
#include "llvm/Support/GenericDomTree.h"
#include <list>
#include <iostream>
#include <boost/format.hpp>
using namespace std;
using namespace xreate;
using namespace boost;
using namespace boost::bimaps;
-namespace xreate {
-namespace dominators {
+namespace xreate { namespace dominators {
struct CFAGraphAdapter;
-struct ScopeNode {
- ScopePacked id;
- std::list<ScopeNode*> nodesFrom;
- std::list<ScopeNode*> nodesTo;
-};
-
-struct CFAGraphAdapter {
- std::list<ScopeNode> nodes;
- ScopeNode* nodeRoot;
-
- ScopeNode* getOrCreateNode(ScopePacked id){
- ScopeNode elemNew; elemNew.id = id;
- auto fnComp = [](const ScopeNode &a, const ScopeNode &b){return a.id < b.id;};
- auto posLowerBound = std::lower_bound(nodes.begin(), nodes.end(), elemNew, fnComp);
-
- if(posLowerBound==nodes.end()|| posLowerBound->id > id){
- return &*nodes.insert(posLowerBound, elemNew);
- }
-
- return &*posLowerBound;
- }
-
- static CFAGraphAdapter* build(const cfa::CFAGraph* graph) {
- CFAGraphAdapter* tree=new CFAGraphAdapter();
-
- enum NODE_MARK{NO_ROOT, POSSIBLE_ROOT};
- std::unordered_map<unsigned int, NODE_MARK> nodeMarks;
- for (const auto& edge: graph->__dependencyRelations){
-
- ScopeNode* nodeTo = tree->getOrCreateNode(edge.first);
- ScopeNode* nodeFrom = tree->getOrCreateNode(edge.second);
- nodeTo->nodesFrom.push_back(nodeFrom);
- nodeFrom->nodesTo.push_back(nodeTo);
-
- nodeMarks.emplace(edge.second, POSSIBLE_ROOT); //weak optional insert
- auto result = nodeMarks.emplace(edge.first, NO_ROOT); //strong insert or update
- if(!result.second){
- result.first->second = NO_ROOT;
- }
- }
-
- std::list<ScopePacked> nodeRoots;
- for(auto nodeMark: nodeMarks){
- if(nodeMark.second == POSSIBLE_ROOT) nodeRoots.push_back(nodeMark.first);
- }
-
- if(nodeRoots.size()>1){
- ScopeNode* nodeGlobalRoot = tree->getOrCreateNode(SCOPE_ABSTRACT_GLOBAL);
- for(auto rootLocal: nodeRoots){
- ScopeNode* nodeLocalRoot = tree->getOrCreateNode(rootLocal);
- nodeLocalRoot->nodesFrom.push_back(nodeGlobalRoot);
- nodeGlobalRoot->nodesTo.push_back(nodeLocalRoot);
- }
-
- } else if (nodeRoots.size()==1){
- tree->nodeRoot = tree->getOrCreateNode(nodeRoots.front());
-
- } else {
- ScopeNode* nodeGlobalRoot = tree->getOrCreateNode(SCOPE_ABSTRACT_GLOBAL);
- tree->nodeRoot = nodeGlobalRoot;
- }
-
- return tree;
- }
-
- CFAGraphAdapter() { }
-};
-}
-} //end of namespace xreate::dominators
-
-namespace llvm {
-using namespace xreate::dominators;
-
-template<>
-struct GraphTraits<ScopeNode*> {
- typedef ScopeNode NodeType;
- typedef std::list<ScopeNode*>::iterator ChildIteratorType;
-
- static ChildIteratorType
- child_begin(NodeType* node) {
- return node->nodesTo.begin();
- }
-
- static ChildIteratorType
- child_end(NodeType* node) {
- return node->nodesTo.end();
- }
-};
-
-template<>
-struct GraphTraits<CFAGraphAdapter*> : public GraphTraits<ScopeNode*> {
- typedef std::list<ScopeNode>::iterator nodes_iterator;
-
- static nodes_iterator
- nodes_begin(CFAGraphAdapter* graph) {
- return graph->nodes.begin();
- }
-
- static nodes_iterator
- nodes_end(CFAGraphAdapter* graph) {
- return graph->nodes.end();
- }
-
- static NodeType*
- getEntryNode(CFAGraphAdapter* F) {
- return F->nodeRoot;
- }
-
- static unsigned int
- size(CFAGraphAdapter* graph) {
- return graph->nodes.size();
- }
-};
-
-
-template<>
-struct GraphTraits<Inverse<ScopeNode*>>
-{
- typedef ScopeNode NodeType;
- typedef std::list<ScopeNode*>::iterator ChildIteratorType;
-
- static ChildIteratorType
- child_begin(NodeType* node) {
- return node->nodesFrom.begin();
- }
-
- static ChildIteratorType
- child_end(NodeType* node) {
- return node->nodesFrom.end();
- }
-};
-}
-
-namespace xreate {
-namespace dominators {
+//struct ScopeNode {
+// ScopePacked id;
+// std::list<ScopeNode*> nodesFrom;
+// std::list<ScopeNode*> nodesTo;
+//};
+//
+//struct CFAGraphAdapter {
+// std::list<ScopeNode> nodes;
+// ScopeNode* nodeRoot;
+//
+// ScopeNode* getOrCreateNode(ScopePacked id){
+// ScopeNode elemNew; elemNew.id = id;
+// auto fnComp = [](const ScopeNode &a, const ScopeNode &b){return a.id < b.id;};
+// auto posLowerBound = std::lower_bound(nodes.begin(), nodes.end(), elemNew, fnComp);
+//
+// if(posLowerBound==nodes.end()|| posLowerBound->id > id){
+// return &*nodes.insert(posLowerBound, elemNew);
+// }
+//
+// return &*posLowerBound;
+// }
+//
+// static CFAGraphAdapter* build(const cfa::CFAGraph* graph) {
+// CFAGraphAdapter* tree=new CFAGraphAdapter();
+//
+// enum NODE_MARK{NO_ROOT, POSSIBLE_ROOT};
+// std::unordered_map<unsigned int, NODE_MARK> nodeMarks;
+// for (const auto& edge: graph->__dependencyRelations){
+//
+// ScopeNode* nodeTo = tree->getOrCreateNode(edge.first);
+// ScopeNode* nodeFrom = tree->getOrCreateNode(edge.second);
+// nodeTo->nodesFrom.push_back(nodeFrom);
+// nodeFrom->nodesTo.push_back(nodeTo);
+//
+// nodeMarks.emplace(edge.second, POSSIBLE_ROOT); //weak optional insert
+// auto result = nodeMarks.emplace(edge.first, NO_ROOT); //strong insert or update
+// if(!result.second){
+// result.first->second = NO_ROOT;
+// }
+// }
+//
+// std::list<ScopePacked> nodeRoots;
+// for(auto nodeMark: nodeMarks){
+// if(nodeMark.second == POSSIBLE_ROOT) nodeRoots.push_back(nodeMark.first);
+// }
+//
+// if(nodeRoots.size()>1){
+// ScopeNode* nodeGlobalRoot = tree->getOrCreateNode(SCOPE_ABSTRACT_GLOBAL);
+// for(auto rootLocal: nodeRoots){
+// ScopeNode* nodeLocalRoot = tree->getOrCreateNode(rootLocal);
+// nodeLocalRoot->nodesFrom.push_back(nodeGlobalRoot);
+// nodeGlobalRoot->nodesTo.push_back(nodeLocalRoot);
+// }
+//
+// } else if (nodeRoots.size()==1){
+// tree->nodeRoot = tree->getOrCreateNode(nodeRoots.front());
+//
+// } else {
+// ScopeNode* nodeGlobalRoot = tree->getOrCreateNode(SCOPE_ABSTRACT_GLOBAL);
+// tree->nodeRoot = nodeGlobalRoot;
+// }
+//
+// return tree;
+// }
+//
+// CFAGraphAdapter() { }
+//};
+//}
+//} //end of namespace xreate::dominators
+//
+//namespace llvm {
+//using namespace xreate::dominators;
+//
+//template<>
+//struct GraphTraits<ScopeNode*> {
+// typedef ScopeNode NodeType;
+// typedef std::list<ScopeNode*>::iterator ChildIteratorType;
+//
+// static ChildIteratorType
+// child_begin(NodeType* node) {
+// return node->nodesTo.begin();
+// }
+//
+// static ChildIteratorType
+// child_end(NodeType* node) {
+// return node->nodesTo.end();
+// }
+//};
+//
+//template<>
+//struct GraphTraits<CFAGraphAdapter*> : public GraphTraits<ScopeNode*> {
+// typedef std::list<ScopeNode>::iterator nodes_iterator;
+//
+// static nodes_iterator
+// nodes_begin(CFAGraphAdapter* graph) {
+// return graph->nodes.begin();
+// }
+//
+// static nodes_iterator
+// nodes_end(CFAGraphAdapter* graph) {
+// return graph->nodes.end();
+// }
+//
+// static NodeType*
+// getEntryNode(CFAGraphAdapter* F) {
+// return F->nodeRoot;
+// }
+//
+// static unsigned int
+// size(CFAGraphAdapter* graph) {
+// return graph->nodes.size();
+// }
+//};
+//
+//
+//template<>
+//struct GraphTraits<Inverse<ScopeNode*>>
+//{
+// typedef ScopeNode NodeType;
+// typedef std::list<ScopeNode*>::iterator ChildIteratorType;
+//
+// static ChildIteratorType
+// child_begin(NodeType* node) {
+// return node->nodesFrom.begin();
+// }
+//
+// static ChildIteratorType
+// child_end(NodeType* node) {
+// return node->nodesFrom.end();
+// }
+//};
+//}
+//
+//namespace xreate {
+//namespace dominators {
+//
+//class DominatorTree : public llvm::DominatorTreeBase<ScopeNode, false> {
+//public:
+// DominatorTree() : llvm::DominatorTreeBase<ScopeNode, false>() {}
+//
+// void
+// run(CFAGraphAdapter& program) {
+// recalculate(program);
+//
+// //extract dominators info
+// for(auto& entry : DomTreeNodes) {
+// if(!entry.getFirst()) continue;
+//
+// dominators.emplace(entry.getFirst()->id, make_pair(entry.getSecond()->getDFSNumIn(), entry.getSecond()->getDFSNumOut()));
+// }
+// }
+//
+// void
+// print(std::ostringstream& output, const std::string& atom) const {
+// boost::format formatAtom(atom+"(%1%, range(%2%, %3%)).");
+//
+// for(auto entry : dominators) {
+// output<<formatAtom%(entry.first)%(entry.second.first)%(entry.second.second)
+// <<std::endl;
+// }
+// }
+//
+//private:
+// DominatorsTreeAnalysisProvider::Dominators dominators;
+//};
+//
+//class PostDominatorTree : public llvm::DominatorTreeBase<ScopeNode, true> {
+//public:
+// PostDominatorTree() : llvm::DominatorTreeBase<ScopeNode, true>() {}
+//
+// void
+// run(CFAGraphAdapter& program) {
+// recalculate(program);
+//
+// //extract dominators info
+// for(auto& entry : DomTreeNodes) {
+// if(!entry.getFirst()) continue;
+//
+// dominators.emplace(entry.getFirst()->id, make_pair(entry.getSecond()->getDFSNumIn(), entry.getSecond()->getDFSNumOut()));
+// }
+// }
+//
+// void
+// print(std::ostringstream& output, const std::string& atom) const {
+// boost::format formatAtom(atom+"(%1%, range(%2%, %3%)).");
+//
+// for(auto entry : dominators) {
+// output<<formatAtom%(entry.first)%(entry.second.first)%(entry.second.second)
+// <<std::endl;
+// }
+// }
+//
+//private:
+// DominatorsTreeAnalysisProvider::Dominators dominators;
+//};
+//
-class DominatorTree : public llvm::DominatorTreeBase<ScopeNode> {
+class DominatorsProviderPrivate{
public:
- DominatorsTreeAnalysisProvider::Dominators dominators;
-
- DominatorTree(bool isPostDom) : llvm::DominatorTreeBase<ScopeNode>(isPostDom) { }
-
- void
- run(CFAGraphAdapter& program) {
- recalculate(program);
+ DominatorsProviderPrivate()
+// : treeForwardDominators(new DominatorTree())
+// , treePostDominators(new PostDominatorTree())
+ { }
- //extract dominators info
- for(auto& entry : DomTreeNodes) {
- if(!entry.getFirst()) continue;
-
- dominators.emplace(entry.getFirst()->id, make_pair(entry.getSecond()->getDFSNumIn(), entry.getSecond()->getDFSNumOut()));
- }
- }
-
- void
- print(std::ostringstream& output, const std::string& atom) const {
- boost::format formatAtom(atom+"(%1%, range(%2%, %3%)).");
-
- for(auto entry : dominators) {
- output<<formatAtom%(entry.first)%(entry.second.first)%(entry.second.second)
- <<endl;
- }
- }
+// boost::scoped_ptr<DominatorTree> treeForwardDominators;
+// boost::scoped_ptr<PostDominatorTree> treePostDominators;
};
+
void
DominatorsTreeAnalysisProvider::run(const cfa::CFAGraph* graph) {
- boost::scoped_ptr<CFAGraphAdapter> program(CFAGraphAdapter::build(graph));
-
- treeForwardDominators->run(*program);
- treePostDominators->run(*program);
+// boost::scoped_ptr<CFAGraphAdapter> program(CFAGraphAdapter::build(graph));
+//
+// treeForwardDominators->run(*program);
+// treePostDominators->run(*program);
}
void
DominatorsTreeAnalysisProvider::print(std::ostringstream& output) const {
- treeForwardDominators->print(output, "cfa_forwdom");
- treePostDominators->print(output, "cfa_postdom");
+// treeForwardDominators->print(output, "cfa_forwdom");
+// treePostDominators->print(output, "cfa_postdom");
}
const DominatorsTreeAnalysisProvider::Dominators&
DominatorsTreeAnalysisProvider::getForwardDominators() const {
- return treeForwardDominators->dominators;
+ //return treeForwardDominators->dominators;
}
const DominatorsTreeAnalysisProvider::Dominators&
DominatorsTreeAnalysisProvider::getPostDominators() const {
- return treePostDominators->dominators;
+ // return treePostDominators->dominators;
}
DominatorsTreeAnalysisProvider::DominatorsTreeAnalysisProvider()
-: treeForwardDominators(new DominatorTree(false))
-, treePostDominators(new DominatorTree(true)) { }
+ : __private(new DominatorsProviderPrivate()) {}
DominatorsTreeAnalysisProvider::~DominatorsTreeAnalysisProvider() { }
-}
-} //end of namespace xreate::dominators
-
-//void
-//CodeScopesTree::print(){
-// typedef llvm::GraphTraits<Node*> Traits;
-// for (size_t i=0; i<size; ++i){
-//
-// for (auto j = Traits::child_begin(&nodes[i]); j!= Traits::child_end(&nodes[i]); ++j){
-// cout << i << "->" << (*j)->scope << endl;
-// }
-// }
-//}
+}} //end of namespace xreate::dominators
\ No newline at end of file
diff --git a/cpp/src/analysis/DominatorsTreeAnalysisProvider.h b/cpp/src/analysis/DominatorsTreeAnalysisProvider.h
index f284208..f3b2aee 100644
--- a/cpp/src/analysis/DominatorsTreeAnalysisProvider.h
+++ b/cpp/src/analysis/DominatorsTreeAnalysisProvider.h
@@ -1,42 +1,43 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: DominatorsTreeAnalysisProvider.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on May 13, 2016, 11:39 AM
*/
#ifndef DOMINATORSTREEANALYSISPROVIDER_H
#define DOMINATORSTREEANALYSISPROVIDER_H
-#include "clasplayer.h"
+#include "transcendlayer.h"
#include <boost/smart_ptr/scoped_ptr.hpp>
namespace xreate{namespace dominators{
- class DominatorTree;
-
- /** \brief Dominators Analysis report */
- class DominatorsTreeAnalysisProvider: public IAnalysisReport {
- public:
- typedef std::pair<ScopePacked, ScopePacked> DominatedRange;
- typedef std::map<ScopePacked, DominatedRange> Dominators;
-
- DominatorsTreeAnalysisProvider();
- virtual ~DominatorsTreeAnalysisProvider();
-
- void run(const cfa::CFAGraph* graph);
- void print(std::ostringstream& output) const override;
-
- const Dominators& getForwardDominators() const;
- const Dominators& getPostDominators() const;
-
- private:
- boost::scoped_ptr<DominatorTree> treeForwardDominators;
- boost::scoped_ptr<DominatorTree> treePostDominators;
- };
+
+class DominatorsProviderPrivate;
+
+/** \brief Dominators Analysis report */
+class DominatorsTreeAnalysisProvider: public IAnalysisReport {
+public:
+ typedef std::pair<ScopePacked, ScopePacked> DominatedRange;
+ typedef std::map<ScopePacked, DominatedRange> Dominators;
+
+ DominatorsTreeAnalysisProvider();
+ virtual ~DominatorsTreeAnalysisProvider();
+
+ void run(const cfa::CFAGraph* graph);
+ void print(std::ostringstream& output) const override;
+
+ const Dominators& getForwardDominators() const;
+ const Dominators& getPostDominators() const;
+
+private:
+ std::unique_ptr<DominatorsProviderPrivate> __private;
+};
+
}} //end of namespace xreate::dominators
#endif /* DOMINATORSTREEANALYSISPROVIDER_H */
diff --git a/cpp/src/analysis/cfagraph.cpp b/cpp/src/analysis/cfagraph.cpp
index adbf469..aa97363 100644
--- a/cpp/src/analysis/cfagraph.cpp
+++ b/cpp/src/analysis/cfagraph.cpp
@@ -1,204 +1,204 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: CFAGraph.cpp
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on June 27, 2016, 2:09 PM
*/
/**
* \file cfagraph.h
* \brief Control Flow Analysis(CFA) graph data
*
*/
#include "analysis/cfagraph.h"
#include "analysis/utils.h"
using namespace xreate::cfa;
using namespace std;
void
CFAGraph::print(std::ostringstream& output) const {
- const std::string& atomBinding = Config::get("clasp.bindings.function");
- const std::string& atomBindingScope = Config::get("clasp.bindings.scope");
+ const std::string& atomBinding = Config::get("transcend.bindings.function");
+ const std::string& atomBindingScope = Config::get("transcend.bindings.scope");
//show function tags
int counterTags = 0;
std::ostringstream bufFunctionNames;
boost::format formatFunction("function(%1%).");
boost::format formatBind(atomBinding + "(%1%, %2%).");
for (auto function: this->__nodesFunction.left) {
const auto tags = this->__functionTags.equal_range(function.first);
if (tags.first == tags.second) {
//no tags
bufFunctionNames << "; " << function.second ;
continue;
}
output << formatFunction % (function.second) << std::endl;
for (const auto& tag_: boost::make_iterator_range(tags)){
const Expression& tag = tag_.second;
list<string> tagRaw = xreate::analysis::compile(tag);
assert(tagRaw.size() == 1);
output << formatBind
% (function.second)
% (tagRaw.front())
<< endl;
++counterTags;
}
}
if (bufFunctionNames.tellp()){
output << formatFunction % (bufFunctionNames.str().substr(2)) << std::endl;
}
if (counterTags == 0) {
output << "%no functtion tags at all" << endl;
}
//declare scopes
boost::format formatScope("scope(0..%1%).");
- output << formatScope % (__clasp->getScopesCount() - 1) << std::endl;
+ output << formatScope % (__transcend->getScopesCount() - 1) << std::endl;
//show context rules:
for (auto rule: this->__contextRules) {
output << ContextRule(rule.second).compile(rule.first) << std::endl;
};
//show scope tags:
counterTags = 0;
boost::format formatScopeBind(atomBindingScope + "(%1%, %2%, strong).");
for (auto entry: this->__scopeTags) {
ScopePacked scopeId = entry.first;
const Expression& tag = entry.second;
list<string> tagRaw = xreate::analysis::compile(tag);
assert(tagRaw.size() == 1);
output << formatScopeBind % scopeId %(tagRaw.front()) << endl;
++counterTags;
}
if (counterTags == 0) {
output << "%scope tags: no tags at all" << endl;
}
output << endl << "%\t\tStatic analysis: CFA" << endl;
//parent connections
//TOTEST CFG parent function
boost::format formatFunctionParent("cfa_parent(%1%, function(%2%)).");
for (const auto &relation: this->__parentFunctionRelations) {
const string& function = this->__nodesFunction.left.at(relation.right);
output << formatFunctionParent % relation.left % function << endl;
}
//TOTEST CFG parent scope
boost::format formatScopeParent("cfa_parent(%1%, scope(%2%)).");
for (const auto &relation: this->__parentScopeRelations) {
output << formatScopeParent % relation.first % relation.second << endl;
}
//call connections
boost::format formatCall("cfa_call(%1%, %2%).");
for (const auto &relation: this->__callRelations) {
const ScopePacked scopeFrom = relation.left;
const string& functionTo = this->__nodesFunction.left.at(relation.right);
output << formatCall % (scopeFrom) % (functionTo) << endl;
}
//function specializations descrtiption
//SECTIONTAG late-context cfa_function_specializations
boost::format formatSpecializations("cfa_function_specializations(%1%, %2%).");
- const list<ManagedFnPtr>& functions = __clasp->ast->getAllFunctions();
+ const list<ManagedFnPtr>& functions = __transcend->ast->getAllFunctions();
for (auto f: functions){
if (f->guard.isValid()){
list<string> guardRaw = xreate::analysis::compile(f->guard);
assert(guardRaw.size() == 1);
output << formatSpecializations % (f->getName()) % (guardRaw.front()) << endl;
}
}
//Dependencies
boost::format formatDependencies("cfa_scope_depends(%1%, %2%).");
for(const auto relation: __dependencyRelations){
output << formatDependencies % relation.first % relation.second << endl;
}
std::multimap<ScopePacked, ScopePacked> __dependencyRelations;
}
void
CFAGraph::addFunctionAnnotations(const std::string& function, const std::map<std::string, Expression>& tags) {
unsigned int fid = registerNodeFunction(function);
for (auto& tag: tags){
__functionTags.emplace(fid, tag.second);
}
}
void
CFAGraph::addScopeAnnotations(const ScopePacked& scope, const std::vector<Expression>& tags){
for (Expression tag: tags){
__scopeTags.emplace(scope, tag);
}
}
void
CFAGraph::addContextRules(const ScopePacked& scope, const std::vector<Expression>& rules){
for (Expression rule: rules){
__contextRules.emplace(scope, rule);
}
}
void
CFAGraph::addCallConnection(const ScopePacked& scopeFrom, const std::string& functionTo) {
unsigned int idFuncTo = registerNodeFunction(functionTo);
__callRelations.insert(CALL_RELATIONS::value_type(scopeFrom, idFuncTo));
}
void
CFAGraph::addParentConnection(const ScopePacked& scope, const std::string& functionParent){
__parentFunctionRelations.insert(PARENT_FUNCTION_RELATIONS::value_type(scope, registerNodeFunction(functionParent)));
}
void
CFAGraph::addParentConnection(const ScopePacked& scope, const ScopePacked& scopeParent){
__parentScopeRelations.emplace(scope, scopeParent);
}
unsigned int
CFAGraph::registerNodeFunction(const std::string& fname){
auto pos = __nodesFunction.left.insert(make_pair(__nodesFunction.size(), fname));
return pos.first->first;
}
void
CFAGraph::addDependency(const ScopePacked& scope, const ScopePacked& scopeDependency){
__dependencyRelations.emplace(scope, scopeDependency);
}
bool CFAGraph::isDependent(const ScopePacked& scope) const{
return __dependencyRelations.count(scope) > 0;
}
void CFAGraph::transmitDependencies(const ScopePacked& scopeTo, const ScopePacked& scopeFrom){
auto range = __dependencyRelations.equal_range(scopeFrom);
std::list<ScopePacked> dependencies;
for (auto pairI = range.first; pairI != range.second; ++pairI){
dependencies.push_back(pairI->second);
}
for(auto dep: dependencies){
__dependencyRelations.emplace(scopeTo, dep);
}
}
diff --git a/cpp/src/analysis/cfagraph.h b/cpp/src/analysis/cfagraph.h
index 7d97e16..743799e 100644
--- a/cpp/src/analysis/cfagraph.h
+++ b/cpp/src/analysis/cfagraph.h
@@ -1,63 +1,63 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: CFAGraph.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on June 27, 2016, 2:09 PM
*/
#ifndef CFAGRAPH_H
#define CFAGRAPH_H
-#include "clasplayer.h"
+#include "transcendlayer.h"
namespace xreate {namespace cfa {
/** \brief Represents CFA analysis data produced by CFAPass */
class CFAGraph: public IAnalysisReport {
public:
typedef boost::bimap<ScopePacked, boost::bimaps::multiset_of<unsigned int>> PARENT_FUNCTION_RELATIONS;
PARENT_FUNCTION_RELATIONS __parentFunctionRelations;
std::map<ScopePacked, ScopePacked> __parentScopeRelations;
std::multimap<ScopePacked, ScopePacked> __dependencyRelations;
typedef boost::bimap<
boost::bimaps::multiset_of<ScopePacked>,
boost::bimaps::multiset_of<unsigned int>,
boost::bimaps::set_of_relation<>
> CALL_RELATIONS;
CALL_RELATIONS __callRelations;
boost::bimap<unsigned int, std::string > __nodesFunction;
std::multimap<unsigned int, Expression> __functionTags;
std::multimap<ScopePacked, Expression> __scopeTags;
std::multimap<ScopePacked, ContextRule> __contextRules;
void print(std::ostringstream& output) const override;
- CFAGraph(ClaspLayer* engine): __clasp(engine){}
+ CFAGraph(TranscendLayer* engine): __transcend(engine){}
void addFunctionAnnotations(const std::string& function, const std::map<std::string, Expression>& tags);
void addScopeAnnotations(const ScopePacked& scope, const std::vector<Expression>&tags);
void addContextRules(const ScopePacked& scope, const std::vector<Expression>&rules);
void addCallConnection(const ScopePacked& scopeFrom, const std::string& functionTo);
void addParentConnection(const ScopePacked& scope, const std::string& functionParent);
void addParentConnection(const ScopePacked& scope, const ScopePacked& scopeParent);
void addDependency(const ScopePacked& scope, const ScopePacked& scopeDependency);
bool isDependent(const ScopePacked& scope) const;
void transmitDependencies(const ScopePacked& scopeTo, const ScopePacked& scopeFrom);
private:
- ClaspLayer* __clasp;
+ TranscendLayer* __transcend;
unsigned int registerNodeFunction(const std::string& fname);
};
}} //end of namespace xreate::cfa
#endif /* CFAGRAPH_H */
diff --git a/cpp/src/analysis/dfagraph.cpp b/cpp/src/analysis/dfagraph.cpp
index 19d9c44..b80240d 100644
--- a/cpp/src/analysis/dfagraph.cpp
+++ b/cpp/src/analysis/dfagraph.cpp
@@ -1,192 +1,192 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: DFAGraph.h
* Author: pgess <v.melnychenko@xreate.org>
*
*/
/**
* \file dfagraph.h
* \brief Data Flow Analysis(DFA) graph data
*
*/
#include "analysis/dfagraph.h"
#include "analysis/utils.h"
using namespace std;
using namespace xreate::analysis;
namespace xreate { namespace dfa {
void
DFACallInstance::print(std::ostringstream& output) const{
boost::format formatArgs;
boost::format formatInstance("dfa_callfn(%1%, %2%).");
switch (type) {
case WEAK:
formatArgs = boost::format("weak(dfa_callargs(%1%, %2%, %3%)).");
break;
case STRONG:
formatArgs = boost::format("weak(dfa_callargs(%1%, %2%, %3%)).\ndfa_callargs(%1%, %2%, %3%).");
break;
}
output << formatInstance
% analysis::writeSymbolNode(retActual)
% fnName
<< endl;
for(std::pair<SymbolPacked, SymbolNode> rec: args) {
SymbolNode argFormal(rec.first);
output << formatArgs
% analysis::writeSymbolNode(retActual)
% analysis::writeSymbolNode(argFormal)
% analysis::writeSymbolNode(rec.second)
<< endl;
}
}
void
DFAGraph::addDependency(const SymbolNode& node, const SymbolNode& subnode){
__dependencies.emplace(node, subnode);
if (boost::get<SymbolPacked>(&node)){
__usedSymbols.insert(node);
}
if (boost::get<SymbolPacked>(&subnode)){
__usedSymbols.insert(node);
}
}
void
DFAGraph::printDependencies(std::ostringstream& output) const{
for(const SymbolNode& root: __roots){
printDependency(output, root, root);
}
}
void
DFAGraph::printDependency(std::ostringstream& output, const SymbolNode& nodeCurrent, const SymbolNode& nodeDependent) const {
auto range = __dependencies.equal_range(nodeCurrent);
for (auto it = range.first; it != range.second; ++it){
if (boost::get<SymbolAnonymous>(&it->second)){
if (!__usedSymbols.count(it->second)){
printDependency(output, it->second, nodeDependent);
continue;
}
}
boost::format formatDependency("dfa_depends(%1%, %2%).");
output << formatDependency
% analysis::writeSymbolNode(nodeDependent)
% analysis::writeSymbolNode(it->second)
<< endl;
printDependency(output, it->second, it->second);
}
}
void
DFAGraph::printInplaceAnnotations(SymbolNode node, const Expression& expression) {
// write down in-place expression tags:
boost::format formatBind("bind(%1%, %2%).");
if (expression.tags.size()) __usedSymbols.insert(node);
for (const pair<std::string, Expression>& tag : expression.tags){
for (const string& tagPart: xreate::analysis::compile(tag.second)) {
__output << formatBind
% analysis::writeSymbolNode(node)
% tagPart
<< endl;
}
}
}
void
DFAGraph::printAlias(const SymbolNode& symbFormal, const SymbolNode& symbActual){
__usedSymbols.insert(symbFormal); __usedSymbols.insert(symbActual);
boost::format formatAlias("dfa_alias(%1%, %2%).");
__output << formatAlias
% analysis::writeSymbolNode(symbFormal)
% analysis::writeSymbolNode(symbActual)
<< endl;
}
void
DFAGraph::printWeakAlias(const SymbolNode& symbFormal, const SymbolNode& symbActual){
__usedSymbols.insert(symbFormal); __usedSymbols.insert(symbActual);
boost::format formatAlias("weak(dfa_alias(%1%, %2%)).");
__output << formatAlias
% analysis::writeSymbolNode(symbFormal)
% analysis::writeSymbolNode(symbActual)
<< endl;
}
void
DFAGraph::printFunctionRet(ManagedFnPtr function, const SymbolNode& symbolRet){
boost::format formatRet("dfa_fnret(%1%, %2%).");
__usedSymbols.insert(symbolRet);
__output << formatRet
% function->getName()
% analysis::writeSymbolNode(symbolRet)
<< endl;
__roots.insert(symbolRet);
}
void
DFAGraph::addCallInstance(DFACallInstance&& instance){
__usedSymbols.insert(instance.retActual);
for(const auto arg: instance.args){
__usedSymbols.insert(SymbolNode(arg.first));
__usedSymbols.insert(arg.second);
}
__callInstances.push_back(std::move(instance));
}
void
DFAGraph::print(std::ostringstream& output) const{
output << endl << "%\t\tStatic analysis: DFA" << endl;
//Dependencies
printDependencies(output);
//Add generated report
output << __output.str() << endl;
//Call instances
for(const DFACallInstance& instance: __callInstances){
instance.print(output);
}
output << endl;
}
void
-DFAGraph::printSymbols(ClaspLayer* clasp){
+DFAGraph::printSymbols(TranscendLayer* transcend){
boost::format formatHint("shint(%1%, \"%2%\").");
for (const SymbolNode& node : __usedSymbols) {
__output << "v(" << analysis::writeSymbolNode(node) << "). ";
if (const SymbolPacked* symbol = boost::get<SymbolPacked>(&node)){
- __output << formatHint % analysis::writeSymbolNode(node) % clasp->getHintForPackedSymbol(*symbol);
+ __output << formatHint % analysis::writeSymbolNode(node) % transcend->getHintForPackedSymbol(*symbol);
}
__output << endl;
}
}
}} //end of namespace xreate::dfa
diff --git a/cpp/src/analysis/dfagraph.h b/cpp/src/analysis/dfagraph.h
index 90a6d6f..a599ac9 100644
--- a/cpp/src/analysis/dfagraph.h
+++ b/cpp/src/analysis/dfagraph.h
@@ -1,58 +1,58 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: dfa.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on June 27, 2016, 1:50 PM
*/
#ifndef DFA_H
#define DFA_H
-#include "clasplayer.h"
+#include "transcendlayer.h"
#include <unordered_set>
namespace xreate {namespace dfa {
enum DFACallInstanceType {
STRONG, WEAK
};
class DFACallInstance {
public:
std::string fnName;
std::vector<std::pair<SymbolPacked, SymbolNode>> args;
SymbolNode retActual;
DFACallInstanceType type;
void print(std::ostringstream& output) const;
};
/** \brief Holds DFA Analysis report produced by DFAPass */
class DFAGraph : public IAnalysisReport {
public:
- // DFAGraph(ClaspLayer* engine): __clasp(engine){}
+ // DFAGraph(TranscendLayer* engine): __transcend(engine){}
virtual void print(std::ostringstream& output) const override;
void addCallInstance(DFACallInstance && instance);
void addDependency(const SymbolNode& node, const SymbolNode& subnodeBlock);
void printInplaceAnnotations(SymbolNode node, const Expression& expression);
void printAlias(const SymbolNode& symbFormal, const SymbolNode& symbActual);
void printWeakAlias(const SymbolNode& symbFormal, const SymbolNode& symbActual);
void printFunctionRet(ManagedFnPtr function, const SymbolNode& symbolRet);
void printDependencies(std::ostringstream& output) const;
- void printSymbols(ClaspLayer* clasp);
+ void printSymbols(TranscendLayer* transcend);
private:
mutable std::ostringstream __output;
std::list<DFACallInstance> __callInstances;
std::unordered_multimap<SymbolNode, SymbolNode> __dependencies;
std::unordered_set<SymbolNode> __usedSymbols;
std::unordered_set<SymbolNode> __roots;
void printDependency(std::ostringstream& output, const SymbolNode& nodeCurrent, const SymbolNode& nodeDependent) const;
};
}} // end of namespace xreate::dfa
#endif /* DFA_H */
diff --git a/cpp/src/analysis/utils.cpp b/cpp/src/analysis/utils.cpp
index 1d5b3d6..63592f5 100644
--- a/cpp/src/analysis/utils.cpp
+++ b/cpp/src/analysis/utils.cpp
@@ -1,165 +1,160 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* aux.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
*/
/**
* \file aux.h
* \brief Data representation in ASP format ready for use by reasoner
*/
#include "utils.h"
#include <boost/format.hpp>
namespace xreate { namespace analysis {
using namespace std;
list<string>
multiplyLists(list<list<string>> &&lists) {
typedef list<string> StringList;
assert(lists.size());
StringList result(*lists.begin());
lists.pop_front();
boost::format concat("%s, %s");
for (StringList &list: lists) {
StringList::const_iterator end = result.end();
for (StringList::iterator expr1I = result.begin(); expr1I != end; ++expr1I) {
if (list.size() == 0) continue;
StringList::const_iterator expr2I = list.begin();
for (int expr2No = 0, size = list.size() - 1; expr2No < size; ++expr2No, ++expr1I)
result.push_back(str(concat %(*expr1I) %(*expr2I)));
*expr1I = str(concat %(*expr1I) %(*expr2I));
}
}
return result;
}
std::list<std::string>
compile(const Expression &e){
list<string> result;
switch (e.op) {
case Operator::CALL: {
assert(e.__state == Expression::COMPOUND);
if(!e.operands.size()){
result.push_back(e.getValueString());
break;
}
std::list<list<string>> operands;
std::transform(e.operands.begin(), e.operands.end(), std::inserter(operands, operands.begin()),
[](const Expression &e) {
return compile(e);
});
list<string> &&operands_ = multiplyLists(std::move(operands));
result.push_back(boost::str(boost::format("%1%(%2%)") % (e.getValueString()) % (boost::algorithm::join(operands_, ", "))));
break;
}
case Operator::NEG: {
assert(e.operands.size() == 1);
const Expression &op = e.operands.at(0);
list<string> &&rawOp = compile(op);
assert(rawOp.size() == 1);
result.push_back((boost::format("not %1%")%(rawOp.front())).str());
break;
};
case Operator::INVALID: {
switch (e.__state) {
case Expression::IDENT:
result.push_back(e.getValueString());
break;
case Expression::NUMBER:
result.push_back(to_string(e.getValueDouble()));
break;
default:
assert(true);
}
break;
}
default: break;
}
-//TODO Null ad hoc ClaspLayer implementation
-// if (e.isNone()){
-// result.push_back(e.__valueS);
-// }
-
assert(result.size());
return result;
}
std::list<std::string>
compileNeg(const Expression &e){
list<string> result;
switch (e.op) {
case Operator::IMPL: {
assert(e.__state == Expression::COMPOUND);
assert(e.operands.size() == 2);
list<string> operands1 = compile(e.operands.at(0));
list<string> operands2 = compile(e.operands.at(1));
boost::format formatNeg("%1%, not %2%");
for (const auto &op1: operands1)
for (const auto &op2: operands2) {
result.push_back(boost::str(formatNeg %(op1) % (op2)));
}
break;
}
case Operator::NEG: {
assert(e.operands.size() == 1);
const Expression &op = e.operands.at(0);
list<string> &&rawOp = compile(op);
assert(rawOp.size() == 1);
result.push_back(rawOp.front());
break;
};
default:
assert(true);
}
return result;
}
//NOTE: Any changes should be reflected in ParseImplAtom<SymbolPacked>,
// ParseImplAtom<SymbolNode>
class VisitorFormatSymbol: public boost::static_visitor<boost::format> {
public:
boost::format operator()(const SymbolPacked& node) const {
boost::format formatSymbNamed("s(%1%,%2%,%3%)");
return formatSymbNamed % node.identifier % node.version % node.scope ;
}
boost::format operator()(const SymbolAnonymous& node) const {
boost::format formatSymbAnonymous("a(%1%)");
return formatSymbAnonymous % node.id;
}
};
boost::format writeSymbolNode(const SymbolNode& symbol){
return boost::apply_visitor(VisitorFormatSymbol(), symbol);
}
}} //end of xreate::analysis
diff --git a/cpp/src/analysis/utils.h b/cpp/src/analysis/utils.h
index 0abaf62..70c2dc1 100644
--- a/cpp/src/analysis/utils.h
+++ b/cpp/src/analysis/utils.h
@@ -1,31 +1,31 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: aux.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on June 26, 2016, 6:49 PM
*/
#ifndef AUX_H
#define AUX_H
#include "ast.h"
-#include "clasplayer.h"
+#include "transcendlayer.h"
#include <list>
#include <boost/format.hpp>
namespace xreate { namespace analysis {
std::list<std::string> compile(const Expression &e);
std::list<std::string> compileNeg(const Expression &e);
std::list<std::string> multiplyLists(std::list<std::list<std::string>> &&lists);
boost::format writeSymbolNode(const SymbolNode& symbol);
}} //end of xreate::analysis
#endif /* AUX_H */
diff --git a/cpp/src/ast.cpp b/cpp/src/ast.cpp
index 91a28c7..d73895f 100644
--- a/cpp/src/ast.cpp
+++ b/cpp/src/ast.cpp
@@ -1,977 +1,977 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
* File: ast.cpp
*/
/**
* \file ast.h
* \brief Syntax Tree and related code
*
* \sa xreate::AST
*/
#include "ast.h"
#include "ExternLayer.h"
#include "analysis/typeinference.h"
#include <stdexcept>
#include <iostream>
//TODO BDecl. forbid multiple body declaration (ExprTyped)
namespace std {
std::size_t
hash<xreate::ScopedSymbol>::operator()(xreate::ScopedSymbol const& s) const {
return s.id ^ (s.version << 2);
}
bool
equal_to<xreate::ScopedSymbol>::operator()(const xreate::ScopedSymbol& __x, const xreate::ScopedSymbol& __y) const {
return __x.id == __y.id && __x.version == __y.version;
}
size_t
hash<xreate::Symbol>::operator()(xreate::Symbol const& s) const {
return hash<xreate::ScopedSymbol>()(s.identifier) ^ ((long int) s.scope << 1);
}
bool
equal_to<xreate::Symbol>::operator()(const xreate::Symbol& __x, const xreate::Symbol& __y) const {
return __x == __y;
};
}
using namespace std;
namespace xreate {
Atom<Identifier_t>::Atom(const std::wstring& value) {
__value = wstring_to_utf8(value);
}
Atom<Identifier_t>::Atom(std::string && name) : __value(name) {
}
const std::string&
Atom<Identifier_t>::get() const {
return __value;
}
Atom<Number_t>::Atom(wchar_t* value) {
//DEBT reconsider number literal recognition
__value = wcstol(value, 0, 10);
}
Atom<Number_t>::Atom(int value)
: __value(value) {
}
double
Atom<Number_t>::get()const {
return __value;
}
Atom<String_t>::Atom(const std::wstring& value) {
assert(value.size() >= 2);
__value = wstring_to_utf8(value.substr(1, value.size() - 2));
}
Atom<String_t>::Atom(std::string && name) : __value(name) {}
const std::string&
Atom<String_t>::get() const {
return __value;
}
class ExpressionHints {
public:
static bool
isStringValueValid(const Expression& e) {
switch (e.__state) {
case Expression::INVALID:
assert(false);
case Expression::IDENT:
case Expression::STRING:
return true;
case Expression::NUMBER:
case Expression::BINDING:
return false;
case Expression::COMPOUND:
{
switch (e.op) {
case Operator::CALL:
return true;
default: return false;
}
}
}
return false;
}
static bool
isDoubleValueValid(const Expression& e) {
switch (e.__state) {
case Expression::NUMBER:
return true;
case Expression::INVALID:
assert(false);
case Expression::IDENT:
case Expression::STRING:
case Expression::BINDING:
return false;
case Expression::COMPOUND: {
switch (e.op) {
case Operator::VARIANT:
return true;
default: return false;
}
}
}
return false;
}
};
class TypesResolver {
private:
const AST* ast;
std::map<std::string, TypeAnnotation> scope;
std::map<TypeAnnotation, int> signatures;
ExpandedType expandType(const TypeAnnotation &t, const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>()) {
return TypesResolver(ast, scope, signatures)(t, args);
}
std::vector<TypeAnnotation>
expandOperands(const std::vector<TypeAnnotation>& operands) {
std::vector<TypeAnnotation> pack;
pack.reserve(operands.size());
std::transform(operands.begin(), operands.end(), std::inserter(pack, pack.end()),
[this](const TypeAnnotation & t) {
return expandType(t);
});
return pack;
}
public:
TypesResolver(const AST* root, const std::map<std::string, TypeAnnotation>& scopeOuter = std::map<std::string, TypeAnnotation>(),
std::map<TypeAnnotation, int> signaturesOuter = std::map<TypeAnnotation, int>())
: ast(root), scope(scopeOuter), signatures(signaturesOuter) {
}
ExpandedType
operator()(const TypeAnnotation &t, const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>()) {
//assert(args.size() == t.bindings.size()); // invalid number of arguments
for (size_t i = 0; i < args.size(); ++i) {
scope[t.bindings.at(i)] = args.at(i);
}
switch (t.__operator) {
case TypeOperator::LIST:
{
assert(t.__operands.size() == 1);
Expanded<TypeAnnotation> elTy = expandType(t.__operands.at(0));
return ExpandedType(TypeAnnotation(tag_array, elTy, 0));
}
case TypeOperator::LIST_NAMED:
{
std::vector<TypeAnnotation>&& packOperands = expandOperands(t.__operands);
auto typNew = TypeAnnotation(TypeOperator::LIST_NAMED, move(packOperands));
typNew.fields = t.fields;
return ExpandedType(move(typNew));
};
case TypeOperator::VARIANT:
{
std::vector<TypeAnnotation>&& packOperands = expandOperands(t.__operands);
auto typNew = TypeAnnotation(TypeOperator::VARIANT, move(packOperands));
typNew.fields = t.fields;
return ExpandedType(move(typNew));
};
case TypeOperator::CALL:
{
std::string alias = t.__valueCustom;
//find in local scope:
TypeAnnotation ty;
if (scope.count(alias)) {
ty = scope.at(alias);
} else if (ast->__indexTypeAliases.count(alias)) {
ty = ast->__indexTypeAliases.at(alias);
} else {
assert(false && "Undefined or external type");
}
std::vector<TypeAnnotation>&& operands = expandOperands(t.__operands);
TypeAnnotation signature(TypeOperator::CALL, move(operands));
signature.__valueCustom = alias;
if (signatures.count(signature)) {
auto link = TypeAnnotation(TypeOperator::LINK,{});
link.conjuctionId = signatures.at(signature);
return ExpandedType(move(link));
}
int cid = signatures.size();
signatures[signature] = cid;
TypeAnnotation tyResult = expandType(ty, operands);
tyResult.conjuctionId = cid;
return ExpandedType(move(tyResult));
};
case TypeOperator::CUSTOM:
{
if (signatures.count(t)) {
return ExpandedType(TypeAnnotation(TypeOperator::LINK, {t}));
}
signatures.emplace(t, signatures.size());
std::string alias = t.__valueCustom;
//find in local scope:
if (scope.count(alias)) {
return expandType(scope.at(alias));
}
- // find in general scope:
+ //find in general scope:
if (ast->__indexTypeAliases.count(alias)) {
return expandType(ast->__indexTypeAliases.at(t.__valueCustom));
}
//if type is unknown keep it as is.
return ExpandedType(TypeAnnotation(t));
};
case TypeOperator::ACCESS:
{
std::string alias = t.__valueCustom;
ExpandedType tyAlias = ExpandedType(TypeAnnotation());
- //find in local scope:
+ //Find in local scope:
if (scope.count(alias)) {
tyAlias = expandType(scope.at(alias));
- //find in global scope:
+ //Find in global scope:
} else if ((ast->__indexTypeAliases.count(alias))) {
tyAlias = expandType(ast->__indexTypeAliases.at(alias));
} else {
assert(false && "Undefined or external type");
}
assert(tyAlias->__operator == TypeOperator::LIST_NAMED);
for (const string& field : t.fields) {
auto fieldIt = std::find(tyAlias->fields.begin(), tyAlias->fields.end(), field);
assert(fieldIt != tyAlias->fields.end() && "unknown field");
int fieldId = fieldIt - tyAlias->fields.begin();
tyAlias = expandType(tyAlias->__operands.at(fieldId));
}
return tyAlias;
}
case TypeOperator::NONE:
{
return ExpandedType(TypeAnnotation(t));
}
default:
assert(false);
}
assert(false);
return ExpandedType(TypeAnnotation());
}
};
TypeAnnotation::TypeAnnotation()
: __operator(TypeOperator::NONE), __value(TypePrimitive::Invalid) {
}
TypeAnnotation::TypeAnnotation(TypePrimitive typ)
: __value(typ) {
}
TypeAnnotation::TypeAnnotation(TypeOperator op, std::initializer_list<TypeAnnotation> operands)
: __operator(op), __operands(operands) {
}
TypeAnnotation::TypeAnnotation(TypeOperator op, std::vector<TypeAnnotation>&& operands)
: __operator(op), __operands(operands) {
}
TypeAnnotation::TypeAnnotation(llvm_array_tag, TypeAnnotation typ, int size)
: TypeAnnotation(TypeOperator::LIST,{typ}) {
__size = size;
}
bool
TypeAnnotation::isValid() const {
return !(__value == TypePrimitive::Invalid && __operator == TypeOperator::NONE);
}
bool
TypeAnnotation::operator<(const TypeAnnotation& t) const {
if (__operator != t.__operator) return __operator < t.__operator;
if (__operator == TypeOperator::NONE)
return __value < t.__value;
if (__operator == TypeOperator::CALL || __operator == TypeOperator::CUSTOM || __operator == TypeOperator::ACCESS) {
if (__valueCustom != t.__valueCustom)
return __valueCustom < t.__valueCustom;
}
return __operands < t.__operands;
}
/*
TypeAnnotation (struct_tag, std::initializer_list<TypeAnnotation>)
{}
*/
void
TypeAnnotation::addBindings(std::vector<Atom<Identifier_t>>&& params) {
bindings.reserve(bindings.size() + params.size());
std::transform(params.begin(), params.end(), std::inserter(bindings, bindings.end()),
[](const Atom<Identifier_t>& ident) {
return ident.get(); });
}
void
TypeAnnotation::addFields(std::vector<Atom<Identifier_t>>&& listFields) {
fields.reserve(fields.size() + listFields.size());
std::transform(listFields.begin(), listFields.end(), std::inserter(fields, fields.end()),
[](const Atom<Identifier_t>& ident) {
return ident.get(); });
}
unsigned int Expression::nextVacantId = 0;
Expression::Expression(const Atom<Number_t>& number)
: Expression() {
__state = NUMBER;
op = Operator::INVALID;
__valueD = number.get();
}
Expression::Expression(const Atom<String_t>& a)
: Expression() {
__state = STRING;
op = Operator::INVALID;
__valueS = a.get();
}
Expression::Expression(const Atom<Identifier_t> &ident)
: Expression() {
__state = IDENT;
op = Operator::INVALID;
__valueS = ident.get();
}
Expression::Expression(const Operator &oprt, std::initializer_list<Expression> params)
: Expression() {
__state = COMPOUND;
op = oprt;
if (op == Operator::CALL) {
assert(params.size() > 0);
Expression arg = *params.begin();
assert(arg.__state == Expression::IDENT);
__valueS = std::move(arg.__valueS);
operands.insert(operands.end(), params.begin() + 1, params.end());
return;
}
operands.insert(operands.end(), params.begin(), params.end());
}
void
Expression::setOp(Operator oprt) {
op = oprt;
switch (op) {
case Operator::INVALID:
__state = INVALID;
break;
default:
__state = COMPOUND;
break;
}
}
void
Expression::addArg(Expression &&arg) {
operands.push_back(arg);
}
void
Expression::addTags(const std::list<Expression> tags) const {
std::transform(tags.begin(), tags.end(), std::inserter(this->tags, this->tags.end()),
[](const Expression & tag) {
return make_pair(tag.getValueString(), tag);
});
}
void
Expression::addBindings(std::initializer_list<Atom<Identifier_t>> params) {
addBindings(params.begin(), params.end());
}
void
Expression::bindType(TypeAnnotation t) {
type = move(t);
}
void
Expression::addBlock(ManagedScpPtr scope) {
blocks.push_back(scope.operator->());
}
const std::vector<Expression>&
Expression::getOperands() const {
return operands;
}
double
Expression::getValueDouble() const {
return __valueD;
}
const std::string&
Expression::getValueString() const {
return __valueS;
}
void
Expression::setValue(const Atom<Identifier_t>&& v) {
__valueS = v.get();
}
void Expression::setValueDouble(double value) {
__valueD = value;
}
bool
Expression::isValid() const {
return (__state != INVALID);
}
bool
Expression::isDefined() const {
return (__state != BINDING && __state != INVALID);
}
Expression::Expression()
: __state(INVALID), op(Operator::INVALID), id(nextVacantId++) {
}
namespace details { namespace inconsistent {
AST::AST() {
Attachments::init<versions::VariableVersion>();
Attachments::init<IdentifierSymbol>();
Attachments::init<SymbolAlias>();
Attachments::init<TypeInferred>();
}
void
AST::addInterfaceData(const ASTInterface& interface, Expression&& data) {
__interfacesData.emplace(interface, move(data));
}
void
AST::addDFAData(Expression &&data) {
__dfadata.push_back(data);
}
void
AST::addExternData(ExternData &&data) {
__externdata.insert(__externdata.end(), data.entries.begin(), data.entries.end());
}
void
AST::add(Function* f) {
__functions.push_back(f);
__indexFunctions.emplace(f->getName(), __functions.size() - 1);
}
void
AST::add(MetaRuleAbstract *r) {
__rules.push_back(r);
}
void
AST::add(TypeAnnotation t, Atom<Identifier_t> alias) {
if (t.__operator == TypeOperator::VARIANT) {
for (int i = 0, size = t.fields.size(); i < size; ++i) {
__dictVariants.emplace(t.fields[i], make_pair(t, i));
}
}
__indexTypeAliases.emplace(alias.get(), move(t));
}
ManagedScpPtr
AST::add(CodeScope* scope) {
this->__scopes.push_back(scope);
return ManagedScpPtr(this->__scopes.size() - 1, &this->__scopes);
}
std::string
AST::getModuleName() {
const std::string name = "moduleTest";
return name;
}
ManagedPtr<Function>
AST::findFunction(const std::string& name) {
int count = __indexFunctions.count(name);
if (!count) {
return ManagedFnPtr::Invalid();
}
assert(count == 1);
auto range = __indexFunctions.equal_range(name);
return ManagedPtr<Function>(range.first->second, &this->__functions);
}
std::list<ManagedFnPtr>
AST::getAllFunctions() const {
const size_t size = __functions.size();
std::list<ManagedFnPtr> result;
for (size_t i = 0; i < size; ++i) {
result.push_back(ManagedFnPtr(i, &this->__functions));
}
return result;
}
//TASK select default specializations
std::list<ManagedFnPtr>
AST::getFunctionSpecializations(const std::string& fnName) const {
auto functions = __indexFunctions.equal_range(fnName);
std::list<ManagedFnPtr> result;
std::transform(functions.first, functions.second, inserter(result, result.end()),
[this](auto f) {
return ManagedFnPtr(f.second, &this->__functions);
});
return result;
}
template<>
ManagedPtr<Function>
AST::begin<Function>() {
return ManagedPtr<Function>(0, &this->__functions);
}
template<>
ManagedPtr<CodeScope>
AST::begin<CodeScope>() {
return ManagedPtr<CodeScope>(0, &this->__scopes);
}
template<>
ManagedPtr<MetaRuleAbstract>
AST::begin<MetaRuleAbstract>() {
return ManagedPtr<MetaRuleAbstract>(0, &this->__rules);
}
void
AST::recognizeVariantConstructor(Expression& function) {
assert(function.op == Operator::CALL);
std::string variant = function.getValueString();
if (!__dictVariants.count(variant)) {
return;
}
auto record = __dictVariants.at(variant);
const TypeAnnotation& typ = record.first;
function.op = Operator::VARIANT;
function.setValueDouble(record.second);
function.type = typ;
}
Atom<Number_t>
AST::recognizeVariantConstructor(Atom<Identifier_t> ident) {
std::string variant = ident.get();
assert(__dictVariants.count(variant) && "Can't recognize variant constructor");
auto record = __dictVariants.at(variant);
return Atom<Number_t>(record.second);
}
void
AST::postponeIdentifier(CodeScope* scope, const Expression& id) {
bucketUnrecognizedIdentifiers.emplace(scope, id);
}
void
AST::recognizePostponedIdentifiers() {
for (const auto& identifier : bucketUnrecognizedIdentifiers) {
if (!identifier.first->recognizeIdentifier(identifier.second)) {
//exception: Ident not found
std::cout << "Unknown symbol: " << identifier.second.getValueString() << std::endl;
assert(false && "Symbol not found");
}
}
}
xreate::AST*
AST::finalize() {
//all finalization steps:
recognizePostponedIdentifiers();
return reinterpret_cast<xreate::AST*> (this);
}
} } //namespace details::incomplete
Expanded<TypeAnnotation>
AST::findType(const std::string& name) {
// find in general scope:
if (__indexTypeAliases.count(name))
return expandType(__indexTypeAliases.at(name));
//if type is unknown keep it as is.
TypeAnnotation t(TypeOperator::CUSTOM,{});
t.__valueCustom = name;
return ExpandedType(move(t));
}
Expanded<TypeAnnotation>
AST::expandType(const TypeAnnotation &t) const {
return TypesResolver(this)(t);
}
ExpandedType
AST::getType(const Expression& expression) {
return typeinference::getType(expression, *this);
}
Function::Function(const Atom<Identifier_t>& name)
: __entry(new CodeScope(0)) {
__name = name.get();
}
void
Function::addTag(Expression&& tag, const TagModifier mod) {
string name = tag.getValueString();
__tags.emplace(move(name), move(tag));
}
const std::map<std::string, Expression>&
Function::getTags() const {
return __tags;
}
CodeScope*
Function::getEntryScope() const {
return __entry;
}
void
Function::addBinding(Atom <Identifier_t>&& name, Expression&& argument) {
__entry->addBinding(move(name), move(argument));
}
const std::string&
Function::getName() const {
return __name;
}
ScopedSymbol
CodeScope::registerIdentifier(const Expression& identifier) {
versions::VariableVersion version = Attachments::get<versions::VariableVersion>(identifier, versions::VERSION_NONE);
auto result = __identifiers.emplace(identifier.getValueString(), __vCounter);
if (result.second) {
++__vCounter;
return { __vCounter - 1, version };
}
return { result.first->second, version };
}
bool
CodeScope::recognizeIdentifier(const Expression& identifier) const {
versions::VariableVersion version = Attachments::get<versions::VariableVersion>(identifier, versions::VERSION_NONE);
const std::string& name = identifier.getValueString();
//search identifier in the current block
if (__identifiers.count(name)) {
VNameId id = __identifiers.at(name);
Symbol s;
s.identifier = ScopedSymbol{id, version};
s.scope = const_cast<CodeScope*> (this);
Attachments::put<IdentifierSymbol>(identifier, s);
return true;
}
//search in the parent scope
if (__parent) {
return __parent->recognizeIdentifier(identifier);
}
return false;
}
ScopedSymbol
CodeScope::getSymbol(const std::string& alias) {
assert(__identifiers.count(alias));
VNameId id = __identifiers.at(alias);
return {id, versions::VERSION_NONE };
}
void
CodeScope::addBinding(Expression&& var, Expression&& argument) {
argument.__state = Expression::BINDING;
__bindings.push_back(var.getValueString());
ScopedSymbol binding = registerIdentifier(var);
__declarations[binding] = move(argument);
}
Symbol
CodeScope::addDefinition(Expression&& var, Expression&& body) {
ScopedSymbol s = registerIdentifier(var);
__declarations[s] = move(body);
return Symbol{s, this};
}
CodeScope::CodeScope(CodeScope* parent)
: __parent(parent) {
}
CodeScope::~CodeScope() {
}
void
CodeScope::setBody(const Expression &body) {
assert(__declarations.count(ScopedSymbol::RetSymbol)==0 && "Attempt to reassign scope body");
__declarations[ScopedSymbol::RetSymbol] = body;
}
const Expression&
CodeScope::getBody() const{
return __declarations.at(ScopedSymbol::RetSymbol);
}
const Expression&
CodeScope::getDefinition(const Symbol& symbol, bool flagAllowUndefined){
const CodeScope* self = symbol.scope;
return self->getDefinition(symbol.identifier, flagAllowUndefined);
}
const Expression&
CodeScope::getDefinition(const ScopedSymbol& symbol, bool flagAllowUndefined) const{
static Expression expressionInvalid;
if (!__declarations.count(symbol)){
if (flagAllowUndefined) return expressionInvalid;
assert(false && "Symbol's declaration not found");
}
return __declarations.at(symbol);
}
void
RuleArguments::add(const Atom<Identifier_t> &arg, DomainAnnotation typ) {
emplace_back(arg.get(), typ);
}
void
RuleGuards::add(Expression&& e) {
push_back(e);
}
MetaRuleAbstract::
MetaRuleAbstract(RuleArguments&& args, RuleGuards&& guards)
: __args(std::move(args)), __guards(std::move(guards)) {
}
MetaRuleAbstract::~MetaRuleAbstract() {
}
RuleWarning::
RuleWarning(RuleArguments&& args, RuleGuards&& guards, Expression&& condition, Atom<String_t>&& message)
: MetaRuleAbstract(std::move(args), std::move(guards)), __message(message.get()), __condition(condition) {
}
RuleWarning::~RuleWarning() {
}
void
-RuleWarning::compile(ClaspLayer& layer) {
+RuleWarning::compile(TranscendLayer& layer) {
//TODO restore addRuleWarning
//layer.addRuleWarning(*this);
}
bool operator<(const ScopedSymbol& s1, const ScopedSymbol& s2) {
return (s1.id < s2.id) || (s1.id == s2.id && s1.version < s2.version);
}
bool operator==(const ScopedSymbol& s1, const ScopedSymbol& s2) {
return (s1.id == s2.id) && (s1.version == s2.version);
}
bool operator<(const Symbol& s1, const Symbol& s2) {
return (s1.scope < s2.scope) || (s1.scope == s2.scope && s1.identifier < s2.identifier);
}
bool operator==(const Symbol& s1, const Symbol& s2) {
return (s1.scope == s2.scope) && (s1.identifier == s2.identifier);
}
bool operator<(const Expression&a, const Expression&b) {
if (a.__state != b.__state) return a.__state < b.__state;
assert(a.__state != Expression::INVALID);
switch (a.__state) {
case Expression::IDENT:
case Expression::STRING:
return a.getValueString() < b.getValueString();
case Expression::NUMBER:
return a.getValueDouble() < b.getValueDouble();
case Expression::COMPOUND:
{
assert(a.blocks.size() == 0);
assert(b.blocks.size() == 0);
if (a.op != b.op) {
return a.op < b.op;
}
bool flagAValid = ExpressionHints::isStringValueValid(a);
bool flagBValid = ExpressionHints::isStringValueValid(b);
if (flagAValid != flagBValid) {
return flagAValid < flagBValid;
}
if (flagAValid) {
if (a.getValueString() != b.getValueString()) {
return a.getValueString() < b.getValueString();
}
}
flagAValid = ExpressionHints::isDoubleValueValid(a);
flagBValid = ExpressionHints::isDoubleValueValid(b);
if (flagAValid != flagBValid) {
return flagAValid < flagBValid;
}
if (flagAValid) {
if (a.getValueDouble() != b.getValueDouble()) {
return a.getValueDouble() < b.getValueDouble();
}
}
if (a.operands.size() != b.operands.size()) {
return (a.operands.size() < b.operands.size());
}
for (size_t i = 0; i < a.operands.size(); ++i) {
bool result = a.operands[i] < b.operands[i];
if (result) return true;
}
return false;
}
case Expression::BINDING:
case Expression::INVALID:
assert(false);
}
return false;
}
bool
Expression::operator==(const Expression& other) const {
if (this->__state != other.__state) return false;
if (ExpressionHints::isStringValueValid(*this)) {
if (this->__valueS != other.__valueS) return false;
}
if (ExpressionHints::isDoubleValueValid(*this)) {
if (this->__valueD != other.__valueD) return false;
}
if (this->__state != Expression::COMPOUND) {
return true;
}
if (this->op != other.op) {
return false;
}
if (this->operands.size() != other.operands.size()) {
return false;
}
for (size_t i = 0; i<this->operands.size(); ++i) {
if (!(this->operands[i] == other.operands[i])) return false;
}
assert(!this->blocks.size());
assert(!other.blocks.size());
return true;
}
const ScopedSymbol
ScopedSymbol::RetSymbol = ScopedSymbol{0, versions::VERSION_NONE};
} //end of namespace xreate
diff --git a/cpp/src/ast.h b/cpp/src/ast.h
index 904bc31..e37d755 100644
--- a/cpp/src/ast.h
+++ b/cpp/src/ast.h
@@ -1,741 +1,741 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
* File: ast.h
*/
#ifndef AST_H
#define AST_H
#include "attachments.h"
#include <vector>
#include <stdlib.h>
#include <string>
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <climits>
#include "utils.h"
#include <algorithm>
namespace llvm {
class Value;
}
namespace xreate {
struct ScopedSymbol;
struct Symbol;
}
namespace std {
template<>
struct hash<xreate::ScopedSymbol> {
std::size_t operator()(xreate::ScopedSymbol const& s) const;
};
template<>
struct equal_to<xreate::ScopedSymbol> {
bool operator()(const xreate::ScopedSymbol& __x, const xreate::ScopedSymbol& __y) const;
};
template<>
struct hash<xreate::Symbol> {
size_t operator()(xreate::Symbol const& s) const;
};
template<>
struct equal_to<xreate::Symbol> {
bool operator()(const xreate::Symbol& __x, const xreate::Symbol& __y) const;
};
}
namespace xreate {
struct String_t {
};
struct Identifier_t {
};
struct Number_t {
};
struct Type_t {
};
template<typename A>
class Atom {
};
//DEBT store line:col for all atoms/identifiers
template<> class
Atom<Identifier_t> {
public:
Atom(const std::wstring& value);
Atom(std::string && name);
const std::string& get() const;
private:
std::string __value;
};
template<>
class Atom<Number_t> {
public:
Atom(wchar_t* value);
Atom(int value);
double get()const;
private:
double __value;
};
template<>
class Atom<String_t> {
public:
Atom(const std::wstring& value);
Atom(std::string && name);
const std::string& get() const;
private:
std::string __value;
};
enum class TypePrimitive {
Invalid, Bool, I8, I32, I64, Num, Int, Float, String
};
enum class TypeOperator {
NONE, CALL, CUSTOM, VARIANT, LIST, LIST_NAMED, ACCESS, LINK
};
struct llvm_array_tag {
};
struct struct_tag {
};
const llvm_array_tag tag_array = llvm_array_tag();
const struct_tag tag_struct = struct_tag();
/**
* \brief Represents type to support type system
*
* This class represents type in denormalized form, i.e. without arguments and aliases substitution
* \sa AST::expandType()
*/
class TypeAnnotation {
public:
TypeAnnotation();
TypeAnnotation(const Atom<Type_t>& typ);
TypeAnnotation(TypePrimitive typ);
TypeAnnotation(llvm_array_tag, TypeAnnotation typ, int size);
TypeAnnotation(TypeOperator op, std::initializer_list<TypeAnnotation> operands);
TypeAnnotation(TypeOperator op, std::vector<TypeAnnotation>&& operands);
void addBindings(std::vector<Atom<Identifier_t>>&& params);
void addFields(std::vector<Atom<Identifier_t>>&& listFields);
bool operator<(const TypeAnnotation& t) const;
// TypeAnnotation (struct_tag, std::initializer_list<TypePrimitive>);
bool isValid() const;
TypeOperator __operator = TypeOperator::NONE;
std::vector<TypeAnnotation> __operands;
TypePrimitive __value;
std::string __valueCustom;
int conjuctionId = -1; //conjunction point id (relevant for recursive types)
uint64_t __size = 0;
std::vector<std::string> fields;
std::vector<std::string> bindings;
private:
};
enum class Operator {
INVALID, UNDEF, ADD, SUB, MUL, DIV,
EQU, NE, NEG, LSS,
LSE, GTR, GTE, LIST,
LIST_RANGE, LIST_NAMED,
CALL, CALL_INTRINSIC,
IMPL/* implication */, MAP,
- FOLD, FOLD_INF, LOOP_CONTEXT,
- INDEX, IF, SWITCH, SWITCH_ADHOC, SWITCH_VARIANT,
+ FOLD, FOLD_INF, INDEX,
+ IF, SWITCH, SWITCH_VARIANT, SWITCH_LATE,
CASE, CASE_DEFAULT, LOGIC_AND,
- ADHOC, CONTEXT_RULE, VARIANT, SEQUENCE
+ CONTEXT_RULE, VARIANT, SEQUENCE
};
class Function;
class AST;
class CodeScope;
class MetaRuleAbstract;
typedef ManagedPtr<Function> ManagedFnPtr;
typedef ManagedPtr<CodeScope> ManagedScpPtr;
typedef ManagedPtr<MetaRuleAbstract> ManagedRulePtr;
const ManagedScpPtr NO_SCOPE = ManagedScpPtr(UINT_MAX, 0);
/**
* \brief Represents every instruction in Xreate's syntax tree
* \attention In case of any changes update xreate::ExpressionHints auxiliary helper as well
*
* Expression is generic building block of syntax tree able to hold node data
* as well as child nodes as operands. Not only instructions use expression for representation in syntax tree
* but annotation as well.
*
* Additionally, `types` as a special kind of annotations use Expression-like data structure TypeAnnotation
* \sa xreate::AST, xreate::TypeAnnotation
*/
//
struct Expression {
friend class CodeScope;
- friend class ClaspLayer;
+ friend class TranscendLayer;
friend class CFAPass;
friend class ExpressionHints;
Expression(const Operator &oprt, std::initializer_list<Expression> params);
Expression(const Atom<Identifier_t>& ident);
Expression(const Atom<Number_t>& number);
Expression(const Atom<String_t>& a);
Expression();
void setOp(Operator oprt);
void addArg(Expression&& arg);
void addBindings(std::initializer_list<Atom<Identifier_t>> params);
void bindType(TypeAnnotation t);
template<class InputIt>
void addBindings(InputIt paramsBegin, InputIt paramsEnd);
void addTags(const std::list<Expression> tags) const;
void addBlock(ManagedScpPtr scope);
const std::vector<Expression>& getOperands() const;
double getValueDouble() const;
void setValueDouble(double value);
const std::string& getValueString() const;
void setValue(const Atom<Identifier_t>&& v);
bool isValid() const;
bool isDefined() const;
bool operator==(const Expression& other) const;
/**
* \brief is it string, number, compound operation and so on
*/
enum {
INVALID, COMPOUND, IDENT, NUMBER, STRING, BINDING
} __state = INVALID;
/**
* \brief Valid for compound State. Holds type of compound operator
*/
Operator op;
/**
* \brief Unique id to identify expression within syntax tree
*/
unsigned int id;
/**
* \brief Exact meaning depends on particular instruction
* \details As an example, named lists/structs hold field names in bindings
*/
std::vector<std::string> bindings;
std::map<std::string, size_t> __indexBindings;
/**
* \brief Holds child instructions as arguments
*/
std::vector<Expression> operands;
/**
* \brief Holds type of instruction's result
*/
TypeAnnotation type;
/**
* \brief Holds additional annotations
*/
mutable std::map<std::string, Expression> tags;
/**
* \brief Child code blocks
* \details For example, If statement holds TRUE-branch as first and FALSE-branch as second block here
*/
std::list<CodeScope*> blocks;
private:
std::string __valueS;
double __valueD;
static unsigned int nextVacantId;
};
bool operator<(const Expression&, const Expression&);
template<class InputIt>
void Expression::addBindings(InputIt paramsBegin, InputIt paramsEnd) {
size_t index = bindings.size();
std::transform(paramsBegin, paramsEnd, std::inserter(bindings, bindings.end()),
[&index, this] (const Atom<Identifier_t> atom) {
std::string key = atom.get();
this->__indexBindings[key] = index++;
return key;
});
}
typedef std::list<Expression> ExpressionList;
enum class TagModifier {
NONE, ASSERT, REQUIRE
};
enum class DomainAnnotation {
FUNCTION, VARIABLE
};
class RuleArguments : public std::vector<std::pair<std::string, DomainAnnotation>>
{
public:
void add(const Atom<Identifier_t>& name, DomainAnnotation typ);
};
class RuleGuards : public std::vector<Expression> {
public:
void add(Expression&& e);
};
-class ClaspLayer;
+class TranscendLayer;
class LLVMLayer;
class MetaRuleAbstract {
public:
MetaRuleAbstract(RuleArguments&& args, RuleGuards&& guards);
virtual ~MetaRuleAbstract();
- virtual void compile(ClaspLayer& layer) = 0;
+ virtual void compile(TranscendLayer& layer) = 0;
protected:
RuleArguments __args;
RuleGuards __guards;
};
class RuleWarning : public MetaRuleAbstract {
- friend class ClaspLayer;
+ friend class TranscendLayer;
public:
RuleWarning(RuleArguments&& args, RuleGuards&& guards, Expression&& condition, Atom<String_t>&& message);
- virtual void compile(ClaspLayer& layer);
+ virtual void compile(TranscendLayer& layer);
~RuleWarning();
private:
std::string __message;
Expression __condition;
};
typedef unsigned int VNameId;
namespace versions {
typedef int VariableVersion;
const VariableVersion VERSION_NONE = -2;
const VariableVersion VERSION_INIT = 0;
}
template<>
struct AttachmentsDict<versions::VariableVersion> {
typedef versions::VariableVersion Data;
static const unsigned int key = 6;
};
struct ScopedSymbol {
VNameId id;
versions::VariableVersion version;
static const ScopedSymbol RetSymbol;
};
struct Symbol {
ScopedSymbol identifier;
const CodeScope * scope;
};
struct IdentifierSymbol{};
struct SymbolAlias{};
template<>
struct AttachmentsDict<IdentifierSymbol> {
typedef Symbol Data;
static const unsigned int key = 7;
};
template<>
struct AttachmentsDict<SymbolAlias> {
typedef Symbol Data;
static const unsigned int key = 9;
};
typedef std::pair<Expression, TagModifier> Tag;
bool operator<(const ScopedSymbol& s1, const ScopedSymbol& s2);
bool operator==(const ScopedSymbol& s1, const ScopedSymbol& s2);
bool operator<(const Symbol& s1, const Symbol& s2);
bool operator==(const Symbol& s1, const Symbol& s2);
/**
* \brief Represents code block and single scope of visibility
*
* Holds single expression as a *body* and set of variable assignments(declarations) used in body's expression
* \sa xreate::AST
*/
class CodeScope {
friend class Function;
friend class PassManager;
public:
CodeScope(CodeScope* parent = 0);
~CodeScope();
/** \brief Set expression as a body */
void setBody(const Expression& body);
/** \brief Returns current code scope body */
const Expression& getBody() const;
/** \brief Adds variable definition to be used in body as well as in other declarations */
Symbol addDefinition(Expression&& var, Expression&& body);
/** \brief Returns symbols' definition */
static const Expression& getDefinition(const Symbol& symbol, bool flagAllowUndefined = false);
const Expression& getDefinition(const ScopedSymbol& symbol, bool flagAllowUndefined = false) const;
/** \brief Adds variable defined elsewhere */
void addBinding(Expression&& var, Expression&& argument);
std::vector<std::string> __bindings;
std::map<std::string, VNameId> __identifiers;
CodeScope* __parent;
//TODO move __definitions to SymbolsAttachments data
//NOTE: definition of return type has index 0
std::unordered_map<ScopedSymbol, Expression> __declarations;
std::vector<Expression> tags;
std::vector<Expression> contextRules;
private:
VNameId __vCounter = 1;
ScopedSymbol registerIdentifier(const Expression& identifier);
public:
bool recognizeIdentifier(const Expression& identifier) const;
ScopedSymbol getSymbol(const std::string& alias);
};
/**
* \brief Represents single function in Xreate's syntax tree
*
* Holds an entry code scope and `guardContext` required for function to operate
* \sa xreate::AST
*/
class Function {
friend class Expression;
friend class CodeScope;
friend class AST;
public:
Function(const Atom<Identifier_t>& name);
/**
* \brief Adds function arguments
*/
void addBinding(Atom <Identifier_t>&& name, Expression&& argument);
/**
* \brief Adds additional function annotations
*/
void addTag(Expression&& tag, const TagModifier mod);
const std::string& getName() const;
const std::map<std::string, Expression>& getTags() const;
CodeScope* getEntryScope() const;
CodeScope* __entry;
std::string __name;
bool isPrefunction = false; //SECTIONTAG adhoc Function::isPrefunction flag
Expression guard;
private:
std::map<std::string, Expression> __tags;
};
class ExternData;
struct ExternEntry {
std::string package;
std::vector<std::string> headers;
};
typedef Expanded<TypeAnnotation> ExpandedType;
struct TypeInferred{};
template<>
struct AttachmentsDict<TypeInferred> {
typedef ExpandedType Data;
static const unsigned int key = 11;
};
enum ASTInterface {
CFA, DFA, Extern, Adhoc
};
struct FunctionSpecialization {
std::string guard;
size_t id;
};
struct FunctionSpecializationQuery {
std::unordered_set<std::string> context;
};
template<>
struct AttachmentsId<Expression>{
static unsigned int getId(const Expression& expression){
return expression.id;
}
};
template<>
struct AttachmentsId<Symbol>{
static unsigned int getId(const Symbol& s){
return s.scope->__declarations.at(s.identifier).id;
}
};
template<>
struct AttachmentsId<ManagedFnPtr>{
static unsigned int getId(const ManagedFnPtr& f){
const Symbol symbolFunction{ScopedSymbol::RetSymbol, f->getEntryScope()};
return AttachmentsId<Symbol>::getId(symbolFunction);
}
};
template<>
struct AttachmentsId<CodeScope*>{
static unsigned int getId(const CodeScope* scope){
const Symbol symbolScope{ScopedSymbol::RetSymbol, scope};
return AttachmentsId<Symbol>::getId(symbolScope);
}
};
template<>
struct AttachmentsId<unsigned int>{
static unsigned int getId(const unsigned int id){
return id;
}
};
class TypesResolver;
namespace details { namespace inconsistent {
/**
* \brief Syntax tree under construction in inconsistent form
*
* Represents Syntax Tree under construction(**inconsistent state**).
* \attention Clients should use rather xreate::AST unless client's code explicitly works with Syntax Tree during construction.
*
* Typically instance only created by xreate::XreateManager and filled in by Parser
* \sa xreate::XreateManager::prepare(std::string&&)
*/
class AST {
friend class xreate::TypesResolver;
public:
AST();
/**
* \brief Adds new function to AST
* \param f Function to register
*/
void add(Function* f);
/**
* \brief Adds new declarative rule to AST
* \param r Declarative Rule
*/
void add(MetaRuleAbstract* r);
/** \brief Registers new code block */
ManagedScpPtr add(CodeScope* scope);
/**
* \brief Add new type to AST
* @param t Type definition
* @param alias Typer name
*/
void add(TypeAnnotation t, Atom<Identifier_t> alias);
/** \brief Current module's name */
std::string getModuleName();
/**
* \brief Looks for function with given name
* \param name Function name to find
* \note Requires that only one function exists under given name
* \return Found function
*/
ManagedPtr<Function> findFunction(const std::string& name);
/** \brief Returns all function in AST */
std::list<ManagedFnPtr> getAllFunctions() const;
/**
* \brief Returns all specializations of a function with a given name
* \param fnName function to find
* \return list of found function specializations
*/
std::list<ManagedFnPtr> getFunctionSpecializations(const std::string& fnName) const;
/**
* \return First element in Functions/Scopes/Rules list depending on template parameter
* \tparam Target either Function or CodeScope or MetaRuleAbstract
*/
template<class Target>
ManagedPtr<Target> begin();
/**
* \brief Performs all necessary steps after AST is built
*
* Performs all finzalisation steps and move AST into consistent state represented by xreate::AST
* \sa xreate::AST
* \return AST in consistent state
*/
xreate::AST* finalize();
typedef std::multimap<std::string, unsigned int> FUNCTIONS_REGISTRY;
std::vector<ExternEntry> __externdata;
std::list<Expression> __dfadata; //TODO move to more appropriate place
std::list<std::string> __rawImports; //TODO move to more appropriate place
std::multimap<ASTInterface, Expression> __interfacesData; //TODO CFA data here.
private:
std::vector<MetaRuleAbstract*> __rules;
std::vector<Function*> __functions;
std::vector<CodeScope*> __scopes;
FUNCTIONS_REGISTRY __indexFunctions;
protected:
std::map<std::string, TypeAnnotation> __indexTypeAliases;
public:
/**
* \brief Stores DFA scheme for later use by DFA Pass
*
* Treats expression as a DFA scheme and feeds to a DFA Pass later
* \paramn Expression DFA Scheme
* \sa xreate::DFAPass
*/
void addDFAData(Expression&& data);
/** \brief Stores data for later use by xreate::ExternLayer */
void addExternData(ExternData&& data);
/**
* \brief Generalized function to store particular data for later use by particular pass
* \param interface Particular Interface
* \param data Particular data
*/
void addInterfaceData(const ASTInterface& interface, Expression&& data);
/**\name Symbols Recognition */
///@{
public:
//TODO revisit enums/variants, move to codescope
/**
* \brief Tries to find out whether expression is Variant constructor
*/
void recognizeVariantConstructor(Expression& function);
Atom<Number_t> recognizeVariantConstructor(Atom<Identifier_t> ident);
private:
std::map<std::string, std::pair<TypeAnnotation, int>> __dictVariants;
public:
std::set<std::pair<CodeScope*, Expression>> bucketUnrecognizedIdentifiers;
public:
/**
* \brief Postpones unrecognized identifier for future second round of recognition
* \param scope Code block identifier is encountered
* \param id Identifier
*/
void postponeIdentifier(CodeScope* scope, const Expression& id);
/** \brief Second round of identifiers recognition done right after AST is fully constructed */
void recognizePostponedIdentifiers();
///@}
};
template<>
ManagedPtr<Function>
AST::begin<Function>();
template<>
ManagedPtr<CodeScope>
AST::begin<CodeScope>();
template<>
ManagedPtr<MetaRuleAbstract>
AST::begin<MetaRuleAbstract>();
} } // namespace details::incomplete
/**
* \brief Xreate's Syntax Tree in consistent state
*
* Syntax Tree has two mutually exclusive possible states:
* - inconsistent state while AST is under construction. Represented by xreate::details::inconsistent::AST
* - consistent state when AST is built and finalize() is done.
*
* This class represents consistent state and should be used everywhere unless client's code explicitly works with AST under construction.
* Consistent AST enables access to additional functions(currently related to type management).
* \sa xreate::details::inconsistent::AST
*/
class AST : public details::inconsistent::AST {
public:
AST() : details::inconsistent::AST() {}
/**
* \brief Computes fully expanded form of type by substituting all arguments and aliases
* \param t Type to expand
* \return Expdanded or normal form of type
* \sa TypeAnnotation
*/
ExpandedType expandType(const TypeAnnotation &t) const;
/**
* Searches type by given name
* \param name Typename to search
* \return Expanded or normal form of desired type
* \note if type name is not found returns new undefined type with this name
*/
ExpandedType findType(const std::string& name);
/**
* Invokes Type Inference Analysis to find out expanded(normal) form expressions's type
* \sa typeinference.h
* \param expression
* \return Type of expression
*/
ExpandedType getType(const Expression& expression);
};
}
#endif // AST_H
diff --git a/cpp/src/attachments.h b/cpp/src/attachments.h
index bf087e8..643f718 100644
--- a/cpp/src/attachments.h
+++ b/cpp/src/attachments.h
@@ -1,180 +1,180 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
* File: attachments.h
* Date: 3/15/15
*/
#ifndef _XREATE_ATTACHMENTS_H_
#define _XREATE_ATTACHMENTS_H_
#include <unordered_map>
#include <vector>
#include <assert.h>
#include <type_traits>
namespace xreate
{
//Attachments dictionary
template<class Tag>
struct AttachmentsDict
{
// typedef void Data;
// static const unsigned int key (next vacant id - 13);
// Defined attachments:
//-----------------------------------------------------
// 1 containers::Implementation
// 3 interpretation::InterpretationData
// 5 interpretation::FunctionInterpretationData
// 6 VariableVersion
// 7 IdentifierSymbol
// 8 versions::VersionImposedDependency
// 9 SymbolAlias
// 11 TypeInferred
// 12 LateBinding
};
template<class Object>
struct AttachmentsId{
//static unsigned int getId(const Object& object);
};
template<class Data>
class IAttachmentsContainer{
protected:
virtual bool __exists(const unsigned int object)=0;
virtual Data& __get(const unsigned int object)=0;
virtual void __put(const unsigned int object, Data data)=0;
public:
template<class Id>
bool exists(const Id& object){
unsigned int id = AttachmentsId<Id>::getId(object);
return __exists(id);
}
template<class Id>
Data& get(const Id& object){
unsigned int id = AttachmentsId<Id>::getId(object);
return __get(id);
}
template<class Id>
Data get(const Id& object, const Data& dataDefault){
unsigned int id = AttachmentsId<Id>::getId(object);
if (! __exists(id)){
return dataDefault;
}
return __get(id);
}
template<class Id>
void put(const Id& object, Data data){
unsigned int id = AttachmentsId<Id>::getId(object);
__put(id, data);
}
virtual ~IAttachmentsContainer(){};
};
template<class Data>
class AttachmentsContainerDefault: public IAttachmentsContainer<Data>{
private:
std::unordered_map<unsigned int, Data> __data;
virtual bool __exists(const unsigned int id){
return __data.count(id);
}
virtual Data& __get(const unsigned int id){
return __data.at(id);
}
virtual void __put(const unsigned int id, Data data){
auto result = __data.emplace(id, data);
assert(result.second);
}
public:
std::unordered_map<unsigned int, Data>& getRawStorage() {
return __data;
}
};
class Attachments{
- private:
- static std::vector<void*> __storage;
-
- template<class Tag>
- using Data = typename AttachmentsDict<Tag>::Data;
-
- public:
- template<class Tag, class Id>
- static bool exists(const Id& object) {
- assert(AttachmentsDict<Tag>::key < __storage.size());
- assert(__storage.at(AttachmentsDict<Tag>::key));
-
- IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
- return self->exists<Id>(object);
- }
-
- template<class Tag, class Id>
- static Data<Tag>& get(const Id& object){
- assert(AttachmentsDict<Tag>::key < __storage.size());
- assert(__storage.at(AttachmentsDict<Tag>::key));
-
- IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
- return self->get<Id>(object);
- }
-
- template<class Tag, class Id>
- static Data<Tag> get(const Id& object, const Data<Tag>& dataDefault){
- assert(AttachmentsDict<Tag>::key < __storage.size());
- assert(__storage.at(AttachmentsDict<Tag>::key));
-
- IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
- return self->get<Id>(object, dataDefault);
- }
-
- template<class Tag, class Id>
- static void put(const Id& object, Data<Tag> data){
- assert(AttachmentsDict<Tag>::key < __storage.size());
- assert(__storage.at(AttachmentsDict<Tag>::key));
-
- IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
- self->put<Id>(object, data);
- }
-
- template<class Tag>
- static void init(){
- unsigned int keyStorage = AttachmentsDict<Tag>::key;
- if (keyStorage+1 > __storage.size()){
- __storage.resize(keyStorage + 1, nullptr);
- }
-
- __storage[keyStorage] = new AttachmentsContainerDefault<Data<Tag>>();
+private:
+ static std::vector<void*> __storage;
+
+ template<class Tag>
+ using Data = typename AttachmentsDict<Tag>::Data;
+
+public:
+ template<class Tag, class Id>
+ static bool exists(const Id& object) {
+ assert(AttachmentsDict<Tag>::key < __storage.size());
+ assert(__storage.at(AttachmentsDict<Tag>::key));
+
+ IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
+ return self->exists(object);
+ }
+
+ template<class Tag, class Id>
+ static Data<Tag>& get(const Id& object){
+ assert(AttachmentsDict<Tag>::key < __storage.size());
+ assert(__storage.at(AttachmentsDict<Tag>::key));
+
+ IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
+ return self->get(object);
+ }
+
+ template<class Tag, class Id>
+ static Data<Tag> get(const Id& object, const Data<Tag>& dataDefault){
+ assert(AttachmentsDict<Tag>::key < __storage.size());
+ assert(__storage.at(AttachmentsDict<Tag>::key));
+
+ IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
+ return self->get(object, dataDefault);
+ }
+
+ template<class Tag, class Id>
+ static void put(const Id& object, Data<Tag> data){
+ assert(AttachmentsDict<Tag>::key < __storage.size());
+ assert(__storage.at(AttachmentsDict<Tag>::key));
+
+ IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
+ self->put(object, data);
+ }
+
+ template<class Tag>
+ static void init(){
+ unsigned int keyStorage = AttachmentsDict<Tag>::key;
+ if (keyStorage+1 > __storage.size()){
+ __storage.resize(keyStorage + 1, nullptr);
}
-
- template<class Tag>
- static void init(IAttachmentsContainer<Data<Tag>>* container){
- unsigned int keyStorage = AttachmentsDict<Tag>::key;
- if (keyStorage+1 > __storage.size()){
- __storage.resize(keyStorage + 1, nullptr);
- }
-
- __storage[keyStorage] = container;
+
+ __storage[keyStorage] = new AttachmentsContainerDefault<Data<Tag>>();
+ }
+
+ template<class Tag>
+ static void init(IAttachmentsContainer<Data<Tag>>* container){
+ unsigned int keyStorage = AttachmentsDict<Tag>::key;
+ if (keyStorage+1 > __storage.size()){
+ __storage.resize(keyStorage + 1, nullptr);
}
+
+ __storage[keyStorage] = container;
+ }
};
}
#endif //_XREATE_ATTACHMENTS_H_
diff --git a/cpp/src/aux/xreatemanager-decorators.cpp b/cpp/src/aux/xreatemanager-decorators.cpp
index 6f3872d..3e40b1a 100644
--- a/cpp/src/aux/xreatemanager-decorators.cpp
+++ b/cpp/src/aux/xreatemanager-decorators.cpp
@@ -1,73 +1,73 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* xreatemanager-decorators.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on July 16, 2017, 4:40 PM
*/
/**
* \file xreatemanager-decorators.h
* \brief \ref xreate::XreateManager decorators to provide various functionality
*/
#include "aux/xreatemanager-decorators.h"
#include "main/Parser.h"
#include "pass/compilepass.h"
#include "pass/cfapass.h"
#include "pass/dfapass.h"
#include "pass/interpretationpass.h"
#include "pass/versionspass.h"
namespace xreate {
void
XreateManagerDecoratorBase::prepareCode(std::string&& code){
grammar::main::Scanner scanner(reinterpret_cast<const unsigned char*>(code.c_str()), code.size());
grammar::main::Parser parser(&scanner);
parser.Parse();
assert(!parser.errors->count && "Parser errors");
PassManager::prepare(parser.root->finalize());
}
void
XreateManagerDecoratorBase::prepareCode(FILE* code){
grammar::main::Scanner scanner(code);
grammar::main::Parser parser(&scanner);
parser.Parse();
assert(!parser.errors->count && "Parser errors");
PassManager::prepare(parser.root->finalize());
}
void
XreateManagerDecoratorBase::analyse(){
- CompilePass::prepareQueries(clasp);
- clasp->run();
+ CompilePass::prepareQueries(transcend);
+ transcend->run();
}
void
XreateManagerDecoratorFull::initPasses(){
cfa::CFAPass* passCFG = new cfa::CFAPass(this);
//TODO is it really DFGPass needs CFGpass?
registerPass(new dfa::DFAPass(this), PassId::DFGPass, passCFG);
registerPass(passCFG, PassId::CFGPass);
this->registerPass(new interpretation::InterpretationPass(this), PassId::InterpretationPass);
this->registerPass(new versions::VersionsPass(this), PassId::VersionsPass);
}
void*
XreateManagerDecoratorFull::run() {
std::unique_ptr<CompilePass> compiler(new compilation::CompilePassCustomDecorators<>(this));
compiler->run();
llvm->print();
llvm->initJit();
return llvm->getFunctionPointer(compiler->getEntryFunction());
}
} //namespace xreate
diff --git a/cpp/src/compilation/advancedinstructions.cpp b/cpp/src/compilation/advancedinstructions.cpp
index fb3406b..3fca3d7 100644
--- a/cpp/src/compilation/advancedinstructions.cpp
+++ b/cpp/src/compilation/advancedinstructions.cpp
@@ -1,459 +1,459 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: InstructionsAdvanced.cpp
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on June 26, 2016, 6:00 PM
*/
/**
* \file advanced.h
* \brief Compilation of statements that require more than one LLVM instruction
*/
#include "compilation/advancedinstructions.h"
#include "compilation/containers.h"
#include "compilation/transformersaturation.h"
#include "query/containers.h"
#include "llvmlayer.h"
#include "ast.h"
using namespace std;
using namespace llvm;
using namespace xreate;
using namespace xreate::containers;
using namespace xreate::compilation;
#define NAME(x) (hintRetVar.empty()? x : hintRetVar)
#define UNUSED(x) (void)(x)
#define EXPAND_CONTEXT \
LLVMLayer* llvm = context.pass->man->llvm; \
compilation::ICodeScopeUnit* scope = context.scope; \
compilation::IFunctionUnit* function = context.function;
AdvancedInstructions::AdvancedInstructions(compilation::Context ctx)
: context(ctx), tyNum(static_cast<llvm::IntegerType*> (ctx.pass->man->llvm->toLLVMType(ExpandedType(TypeAnnotation(TypePrimitive::Num))))) {
}
llvm::Value*
AdvancedInstructions::compileMapSolidOutput(const Expression &expr, const std::string hintRetVar) {
EXPAND_CONTEXT UNUSED(scope);
//initialization
Symbol symbolIn = Attachments::get<IdentifierSymbol>(expr.getOperands()[0]);
ImplementationRec<SOLID> implIn = containers::Query::queryImplementation(symbolIn).extract<SOLID>(); // impl of input list
size_t size = implIn.size;
CodeScope* scopeLoop = expr.blocks.front();
std::string varEl = scopeLoop->__bindings[0];
Iterator* it = Iterator::create(context, symbolIn);
llvm::Value *rangeFrom = it->begin();
llvm::Value *rangeTo = it->end();
//definitions
ArrayType* tyNumArray = (ArrayType*) (llvm->toLLVMType(ExpandedType(TypeAnnotation(tag_array, TypePrimitive::Num, size))));
llvm::IRBuilder<> &builder = llvm->builder;
- llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "loop", function->raw);
+ llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm->llvmContext, "loop", function->raw);
llvm::BasicBlock *blockBeforeLoop = builder.GetInsertBlock();
- llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "postloop", function->raw);
+ llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm->llvmContext, "postloop", function->raw);
Value* dataOut = llvm->builder.CreateAlloca(tyNumArray, ConstantInt::get(tyNum, size), NAME("map"));
// * initial check
Value* condBefore = builder.CreateICmpSLE(rangeFrom, rangeTo);
builder.CreateCondBr(condBefore, blockLoop, blockAfterLoop);
// create PHI:
builder.SetInsertPoint(blockLoop);
llvm::PHINode *stateLoop = builder.CreatePHI(tyNum, 2, "mapIt");
stateLoop->addIncoming(rangeFrom, blockBeforeLoop);
// loop body:
Value* elIn = it->get(stateLoop, varEl);
compilation::ICodeScopeUnit* scopeLoopUnit = function->getScopeUnit(scopeLoop);
scopeLoopUnit->bindArg(elIn, move(varEl));
Value* elOut = scopeLoopUnit->compile();
Value *pElOut = builder.CreateGEP(dataOut, ArrayRef<Value *>(std::vector<Value*>{ConstantInt::get(tyNum, 0), stateLoop}));
builder.CreateStore(elOut, pElOut);
//next iteration preparing
Value *stateLoopNext = builder.CreateAdd(stateLoop, llvm::ConstantInt::get(tyNum, 1));
stateLoop->addIncoming(stateLoopNext, builder.GetInsertBlock());
//next iteration checks:
Value* condAfter = builder.CreateICmpSLE(stateLoopNext, rangeTo);
builder.CreateCondBr(condAfter, blockLoop, blockAfterLoop);
//finalization:
builder.SetInsertPoint(blockAfterLoop);
return dataOut;
}
Value*
AdvancedInstructions::compileArrayIndex(llvm::Value* aggregate, std::vector<llvm::Value *> indexes, std::string hintRetVar) {
EXPAND_CONTEXT UNUSED(function); UNUSED(scope);
indexes.insert(indexes.begin(), llvm::ConstantInt::get(tyNum, 0));
llvm::Value *pEl = llvm->builder.CreateGEP(aggregate, llvm::ArrayRef<llvm::Value *>(indexes));
return llvm->builder.CreateLoad(pEl, NAME("el"));
}
Value*
AdvancedInstructions::compileStructIndex(llvm::Value* aggregate, const ExpandedType& t, const std::string& idx) {
EXPAND_CONTEXT UNUSED(scope); UNUSED(function);
TypeUtils types(llvm);
std::vector<std::string>&& fields = types.getStructFields(t);
for (unsigned i = 0, size = fields.size(); i < size; ++i) {
if (fields.at(i) == idx) {
//dereference pointer
if (types.isPointer(t)) {
llvm::Value* addr = llvm->builder.CreateConstGEP2_32(nullptr, aggregate, 0, i);
return llvm->builder.CreateLoad(addr);
}
return llvm->builder.CreateExtractValue(aggregate, llvm::ArrayRef<unsigned>{i});
}
}
assert(false && "not found required struct field");
return nullptr;
}
llvm::Value*
AdvancedInstructions::compileFold(const Expression& fold, const std::string& hintRetVar) {
EXPAND_CONTEXT
assert(fold.op == Operator::FOLD);
//initialization:
Symbol varInSymbol = Attachments::get<IdentifierSymbol>(fold.getOperands()[0]);
Implementation info = Query::queryImplementation(varInSymbol);
Iterator* it = Iterator::create(context, varInSymbol);
llvm::Value* rangeBegin = it->begin();
llvm::Value* rangeEnd = it->end();
llvm::Value* accumInit = scope->process(fold.getOperands()[1]);
std::string varIn = fold.getOperands()[0].getValueString();
std::string varAccum = fold.bindings[1];
std::string varEl = fold.bindings[0];
llvm::BasicBlock *blockBeforeLoop = llvm->builder.GetInsertBlock();
std::unique_ptr<TransformerSaturation> transformerSaturation(new TransformerSaturation(blockBeforeLoop, context.pass->managerTransformations));
- llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "fold", function->raw);
- llvm::BasicBlock *blockLoopBody = llvm::BasicBlock::Create(llvm::getGlobalContext(), "fold_body", function->raw);
- llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "fold_after", function->raw);
- llvm::BasicBlock *blockNext = llvm::BasicBlock::Create(llvm::getGlobalContext(), "fold_next", function->raw);
+ llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm->llvmContext, "fold", function->raw);
+ llvm::BasicBlock *blockLoopBody = llvm::BasicBlock::Create(llvm->llvmContext, "fold_body", function->raw);
+ llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm->llvmContext, "fold_after", function->raw);
+ llvm::BasicBlock *blockNext = llvm::BasicBlock::Create(llvm->llvmContext, "fold_next", function->raw);
llvm->builder.CreateBr(blockLoop);
// * create phi
llvm->builder.SetInsertPoint(blockLoop);
llvm::PHINode *accum = llvm->builder.CreatePHI(accumInit->getType(), 2, varAccum);
accum->addIncoming(accumInit, blockBeforeLoop);
llvm::PHINode *itLoop = llvm->builder.CreatePHI(rangeBegin->getType(), 2, "foldIt");
itLoop->addIncoming(rangeBegin, blockBeforeLoop);
// * loop checks
Value* condRange = llvm->builder.CreateICmpNE(itLoop, rangeEnd);
llvm->builder.CreateCondBr(condRange, blockLoopBody, blockAfterLoop);
// * loop body
llvm->builder.SetInsertPoint(blockLoopBody);
CodeScope* scopeLoop = fold.blocks.front();
compilation::ICodeScopeUnit* loopUnit = function->getScopeUnit(scopeLoop);
Value* elIn = it->get(itLoop);
loopUnit->bindArg(accum, move(varAccum));
loopUnit->bindArg(elIn, move(varEl));
Value* accumNext = loopUnit->compile();
// * Loop saturation checks
bool flagSaturationTriggered = transformerSaturation->insertSaturationChecks(blockNext, blockAfterLoop, context);
llvm::BasicBlock* blockSaturation = llvm->builder.GetInsertBlock();
if (!flagSaturationTriggered){
llvm->builder.CreateBr(blockNext);
}
// * computing next iteration state
llvm->builder.SetInsertPoint(blockNext);
Value *itLoopNext = it->advance(itLoop);
accum->addIncoming(accumNext, llvm->builder.GetInsertBlock());
itLoop->addIncoming(itLoopNext, llvm->builder.GetInsertBlock());
llvm->builder.CreateBr(blockLoop);
// * finalization:
llvm->builder.SetInsertPoint(blockAfterLoop);
if (!flagSaturationTriggered){
return accum;
}
llvm::PHINode* result = llvm->builder.CreatePHI(accumInit->getType(), 2);
result->addIncoming(accum, blockLoop);
result->addIncoming(accumNext, blockSaturation);
return result;
}
llvm::Value*
AdvancedInstructions::compileFoldInf(const Expression& fold, const std::string& hintRetVar) {
EXPAND_CONTEXT
assert(fold.op == Operator::FOLD_INF);
std::string accumName = fold.bindings[0];
llvm::Value* accumInit = scope->process(fold.getOperands()[0]);
llvm::BasicBlock *blockBeforeLoop = llvm->builder.GetInsertBlock();
- llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "foldinf", function->raw);
- llvm::BasicBlock *blockNext = llvm::BasicBlock::Create(llvm::getGlobalContext(), "foldinf_next", function->raw);
- llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "foldinf_post", function->raw);
+ llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm->llvmContext, "foldinf", function->raw);
+ llvm::BasicBlock *blockNext = llvm::BasicBlock::Create(llvm->llvmContext, "foldinf_next", function->raw);
+ llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm->llvmContext, "foldinf_post", function->raw);
std::unique_ptr<TransformerSaturation> transformerSaturation(new TransformerSaturation(blockBeforeLoop, context.pass->managerTransformations));
llvm->builder.CreateBr(blockLoop);
// * create phi
llvm->builder.SetInsertPoint(blockLoop);
llvm::PHINode *accum = llvm->builder.CreatePHI(accumInit->getType(), 2, accumName);
accum->addIncoming(accumInit, blockBeforeLoop);
// * loop body
CodeScope* scopeLoop = fold.blocks.front();
compilation::ICodeScopeUnit* unitLoop = function->getScopeUnit(scopeLoop);
unitLoop->bindArg(accum, move(accumName));
Value* accumNext = unitLoop->compile();
// * Loop saturation checks
bool flagSaturationTriggered = transformerSaturation->insertSaturationChecks(blockNext, blockAfterLoop, context);
assert(flagSaturationTriggered);
// * computing next iteration state
llvm->builder.SetInsertPoint(blockNext);
accum->addIncoming(accumNext, llvm->builder.GetInsertBlock());
llvm->builder.CreateBr(blockLoop);
// finalization:
llvm->builder.SetInsertPoint(blockAfterLoop);
return accumNext;
}
llvm::Value*
AdvancedInstructions::compileIf(const Expression& exprIf, const std::string& hintRetVar) {
EXPAND_CONTEXT
const Expression& condExpr = exprIf.getOperands()[0];
llvm::IRBuilder<>& builder = llvm->builder;
assert(builder.GetInsertBlock() == scope->currentBlockRaw);
//initialization:
- llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ifAfter", function->raw);
- llvm::BasicBlock *blockTrue = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ifTrue", function->raw);
- llvm::BasicBlock *blockFalse = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ifFalse", function->raw);
+ llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm->llvmContext, "ifAfter", function->raw);
+ llvm::BasicBlock *blockTrue = llvm::BasicBlock::Create(llvm->llvmContext, "ifTrue", function->raw);
+ llvm::BasicBlock *blockFalse = llvm::BasicBlock::Create(llvm->llvmContext, "ifFalse", function->raw);
llvm::Value* cond = scope->process(condExpr);
builder.SetInsertPoint(blockTrue);
CodeScope* scopeTrue = exprIf.blocks.front();
llvm::Value* resultTrue = function->getScopeUnit(scopeTrue)->compile();
llvm::BasicBlock * blockTrueEnd = builder.GetInsertBlock();
builder.CreateBr(blockEpilog);
builder.SetInsertPoint(blockFalse);
CodeScope* scopeFalse = exprIf.blocks.back();
llvm::Value* resultFalse = function->getScopeUnit(scopeFalse)->compile();
llvm::BasicBlock * blockFalseEnd = builder.GetInsertBlock();
builder.CreateBr(blockEpilog);
builder.SetInsertPoint(scope->currentBlockRaw);
llvm->builder.CreateCondBr(cond, blockTrue, blockFalse);
builder.SetInsertPoint(blockEpilog);
llvm::PHINode *ret = builder.CreatePHI(resultTrue->getType(), 2, NAME("if"));
ret->addIncoming(resultTrue, blockTrueEnd);
ret->addIncoming(resultFalse, blockFalseEnd);
return ret;
}
//TODO Switch: default variant no needed when all possible conditions are considered
llvm::Value*
AdvancedInstructions::compileSwitch(const Expression& exprSwitch, const std::string& hintRetVar) {
EXPAND_CONTEXT UNUSED(function);
AST* root = context.pass->man->root;
llvm::IRBuilder<>& builder = llvm->builder;
assert(exprSwitch.operands.size() >= 2);
assert(exprSwitch.operands[1].op == Operator::CASE_DEFAULT && "No default case in Switch Statement");
int countCases = exprSwitch.operands.size() - 1;
llvm::BasicBlock* blockProlog = builder.GetInsertBlock();
- llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm::getGlobalContext(), "switchAfter", function->raw);
+ llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm->llvmContext, "switchAfter", function->raw);
builder.SetInsertPoint(blockEpilog);
llvm::Type* exprSwitchType = llvm->toLLVMType(root->getType(exprSwitch));
llvm::PHINode *ret = builder.CreatePHI(exprSwitchType, countCases, NAME("switch"));
builder.SetInsertPoint(blockProlog);
llvm::Value * conditionSwitch = scope->process(exprSwitch.operands[0]);
- llvm::BasicBlock *blockDefault = llvm::BasicBlock::Create(llvm::getGlobalContext(), "caseDefault", function->raw);
+ llvm::BasicBlock *blockDefault = llvm::BasicBlock::Create(llvm->llvmContext, "caseDefault", function->raw);
llvm::SwitchInst * instructionSwitch = builder.CreateSwitch(conditionSwitch, blockDefault, countCases);
for (int size = exprSwitch.operands.size(), i = 2; i < size; ++i) {
- llvm::BasicBlock *blockCase = llvm::BasicBlock::Create(llvm::getGlobalContext(), "case" + std::to_string(i), function->raw);
+ llvm::BasicBlock *blockCase = llvm::BasicBlock::Create(llvm->llvmContext, "case" + std::to_string(i), function->raw);
llvm::Value* condCase = function->getScopeUnit(exprSwitch.operands[i].blocks.front())->compile();
builder.SetInsertPoint(blockCase);
llvm::Value* resultCase = function->getScopeUnit(exprSwitch.operands[i].blocks.back())->compile();
builder.CreateBr(blockEpilog);
ret->addIncoming(resultCase, builder.GetInsertBlock());
builder.SetInsertPoint(blockProlog);
instructionSwitch->addCase(dyn_cast<llvm::ConstantInt>(condCase), blockCase);
}
//compile default block:
builder.SetInsertPoint(blockDefault);
CodeScope* scopeDefault = exprSwitch.operands[1].blocks.front();
llvm::Value* resultDefault = function->getScopeUnit(scopeDefault)->compile();
builder.CreateBr(blockEpilog);
ret->addIncoming(resultDefault, builder.GetInsertBlock());
builder.SetInsertPoint(blockEpilog);
return ret;
}
llvm::Value*
AdvancedInstructions::compileSwitchVariant(const Expression& exprSwitch, const std::string& hintRetVar) {
EXPAND_CONTEXT UNUSED(function);
AST* root = context.pass->man->root;
llvm::IRBuilder<>& builder = llvm->builder;
- llvm::Type* typI8= llvm::Type::getInt8Ty(llvm::getGlobalContext());
+ llvm::Type* typI8= llvm::Type::getInt8Ty(llvm->llvmContext);
const ExpandedType& typVariant = root->getType(exprSwitch.operands.at(0));
llvm::Type* typVariantRaw = llvm->toLLVMType(typVariant);
assert(typVariant->__operands.size() == exprSwitch.operands.size() - 1 && "Ill-formed Switch Variant");
int casesCount = exprSwitch.operands.size();
llvm::BasicBlock* blockProlog = builder.GetInsertBlock();
- llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm::getGlobalContext(), "switchAfter", function->raw);
+ llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm->llvmContext, "switchAfter", function->raw);
builder.SetInsertPoint(blockEpilog);
llvm::Type* resultType = llvm->toLLVMType(root->getType(exprSwitch));
llvm::PHINode *ret = builder.CreatePHI(resultType, casesCount, NAME("switch"));
builder.SetInsertPoint(blockProlog);
llvm::Value * conditionSwitchRaw = scope->process(exprSwitch.operands.at(0));
llvm::Value* idRaw = builder.CreateExtractValue(conditionSwitchRaw, llvm::ArrayRef<unsigned>({0}));
//Dereference preparation
const bool flagDoDerefence = llvm::cast<llvm::StructType>(typVariantRaw)->getStructNumElements() > 1;
llvm::Value* addrAsStorage = nullptr;
if (flagDoDerefence){
llvm::Type* typStorageRaw = llvm::cast<llvm::StructType>(typVariantRaw)->getElementType(1);
llvm::Value* storageRaw = builder.CreateExtractValue(conditionSwitchRaw, llvm::ArrayRef<unsigned>({1}));
addrAsStorage = llvm->builder.CreateAlloca(typStorageRaw);
llvm->builder.CreateStore(storageRaw, addrAsStorage);
}
llvm::SwitchInst * instructionSwitch = builder.CreateSwitch(idRaw, nullptr, casesCount);
llvm::BasicBlock* blockDefaultUndefined;
std::list<CodeScope*>::const_iterator scopeCaseIt = exprSwitch.blocks.begin();
for (int instancesSize = exprSwitch.operands.size()-1, instId = 0; instId < instancesSize; ++instId) {
- llvm::BasicBlock *blockCase = llvm::BasicBlock::Create(llvm::getGlobalContext(), "case" + std::to_string(instId), function->raw);
+ llvm::BasicBlock *blockCase = llvm::BasicBlock::Create(llvm->llvmContext, "case" + std::to_string(instId), function->raw);
builder.SetInsertPoint(blockCase);
ICodeScopeUnit* unitCase = function->getScopeUnit(*scopeCaseIt);
//Actual variant Derefence
if (flagDoDerefence) {
assert(exprSwitch.bindings.size() && "Switch condition alias not found");
string identCondition = exprSwitch.bindings.front();
const ExpandedType& instType = ExpandedType(typVariant->__operands.at(instId));
llvm::Type* instTypeRaw = llvm->toLLVMType(instType);
llvm::Value* addrAsInst = llvm->builder.CreateBitOrPointerCast(addrAsStorage, instTypeRaw->getPointerTo());
llvm::Value* instRaw = llvm->builder.CreateLoad(instTypeRaw, addrAsInst);
const Symbol& identSymb = unitCase->bindArg(instRaw, move(identCondition));
Attachments::put<TypeInferred>(identSymb, instType);
}
llvm::Value* resultCase = function->getScopeUnit(*scopeCaseIt)->compile();
builder.CreateBr(blockEpilog);
ret->addIncoming(resultCase, blockDefaultUndefined = builder.GetInsertBlock());
builder.SetInsertPoint(blockProlog);
instructionSwitch->addCase(dyn_cast<llvm::ConstantInt>(llvm::ConstantInt::get(typI8, exprSwitch.operands.at(instId+1).getValueDouble())), blockCase);
++scopeCaseIt;
}
instructionSwitch->setDefaultDest(blockDefaultUndefined);
builder.SetInsertPoint(blockEpilog);
return ret;
}
//TODO recognize cases to make const arrays/stored in global mem/stack alloced.
llvm::Value*
AdvancedInstructions::compileListAsSolidArray(const Expression &expr, const std::string& hintRetVar) {
EXPAND_CONTEXT UNUSED(scope); UNUSED(function);
AST* root = context.pass->man->root;
const size_t& length = expr.getOperands().size();
const Expression& expression = expr;
llvm::Value* zero = ConstantInt::get(tyNum, 0);
llvm::Value* one = ConstantInt::get(tyNum, 1);
ExpandedType typAggrExpanded = root->getType(expression);
assert(typAggrExpanded->__operator == TypeOperator::LIST);
llvm::Type* typEl = llvm->toLLVMType(ExpandedType(typAggrExpanded->__operands[0]));
ArrayType* typAggr = (ArrayType*) llvm::ArrayType::get(typEl, length);
- llvm::Value* list = llvm->builder.CreateAlloca(typAggr, ConstantInt::get(Type::getInt32Ty(llvm::getGlobalContext()), length, false), hintRetVar);
+ llvm::Value* list = llvm->builder.CreateAlloca(typAggr, ConstantInt::get(Type::getInt32Ty(llvm->llvmContext), length, false), hintRetVar);
const std::vector<Expression>& operands = expression.getOperands();
llvm::Value* addrOperand = llvm->builder.CreateGEP(typAggr, list, ArrayRef<Value *>(std::vector<Value*>{zero, zero}));
llvm->builder.CreateStore(scope->process(operands.front()), addrOperand) ;
for (auto i=++operands.begin(); i!=operands.end(); ++i){
addrOperand = llvm->builder.CreateGEP(typEl, addrOperand, ArrayRef<Value *>(std::vector<Value*>{one}));
llvm->builder.CreateStore(scope->process(*i), addrOperand) ;
}
return list;
// Value* listDest = l.builder.CreateAlloca(typList, ConstantInt::get(typI32, __size), *hintRetVar);
// l.buil1der.CreateMemCpy(listDest, listSource, __size, 16);
}
llvm::Value*
AdvancedInstructions::compileConstantStringAsPChar(const string& data, const std::string& hintRetVar) {
EXPAND_CONTEXT UNUSED(function); UNUSED(scope);
- Type* typPchar = PointerType::getUnqual(Type::getInt8Ty(llvm::getGlobalContext()));
+ Type* typPchar = PointerType::getUnqual(Type::getInt8Ty(llvm->llvmContext));
//ArrayType* typStr = (ArrayType*) (llvm->toLLVMType(ExpandedType(TypeAnnotation(tag_array, TypePrimitive::I8, size+1))));
/*
std::vector<Constant *> chars;
chars.reserve(size+1);
for (size_t i=0; i< size; ++i){
chars[i] = ConstantInt::get(typI8, (unsigned char) data[i]);
}
chars[size] = ConstantInt::get(typI8, 0);
*/
- Value* rawData = ConstantDataArray::getString(llvm::getGlobalContext(), data);
- Value* rawPtrData = llvm->builder.CreateAlloca(rawData->getType(), ConstantInt::get(Type::getInt32Ty(llvm::getGlobalContext()), 1, false));
+ Value* rawData = ConstantDataArray::getString(llvm->llvmContext, data);
+ Value* rawPtrData = llvm->builder.CreateAlloca(rawData->getType(), ConstantInt::get(Type::getInt32Ty(llvm->llvmContext), 1, false));
llvm->builder.CreateStore(rawData, rawPtrData);
return llvm->builder.CreateCast(llvm::Instruction::BitCast, rawPtrData, typPchar, hintRetVar);
}
llvm::Value*
AdvancedInstructions::compileSequence(const Expression &expr){
EXPAND_CONTEXT UNUSED(scope); UNUSED(llvm);
llvm::Value* result;
for(CodeScope* scope: expr.blocks){
result = function->getScopeUnit(scope)->compile();
}
return result;
}
diff --git a/cpp/src/compilation/advancedinstructions.h b/cpp/src/compilation/advancedinstructions.h
index 22a97cb..7b0fbfb 100644
--- a/cpp/src/compilation/advancedinstructions.h
+++ b/cpp/src/compilation/advancedinstructions.h
@@ -1,54 +1,52 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: AdvancedInstructions.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on June 26, 2016, 6:00 PM
*/
#ifndef INSTRUCTIONSADVANCED_H
#define INSTRUCTIONSADVANCED_H
#include "ast.h"
#include "llvmlayer.h"
#include "pass/compilepass.h"
#include <vector>
namespace xreate {
namespace compilation {
class AdvancedInstructions {
public:
AdvancedInstructions(compilation::Context ctx);
llvm::Value* compileArrayIndex(llvm::Value* aggregate, std::vector<llvm::Value *> indexes, std::string ident = "");
llvm::Value* compileStructIndex(llvm::Value* aggregate, const ExpandedType& t, const std::string& idx);
/*
* - map Computation -> Llvm_Array: Prohibited, we do not know a result size
* - map Llvm_Array -> Computation: considered in `compileGetElement`
* - map Llvm_Array -> Llvm_Array considered by this method
*/
llvm::Value* compileMapSolidOutput(const Expression &expr, const std::string hintRetVar = "");
llvm::Value* compileFold(const Expression& fold, const std::string& ident="");
llvm::Value* compileFoldInf(const Expression& fold, const std::string& ident="");
- //DISABLEDFEATURE Context Loop
- llvm::Value* compileLoopContext(const Expression& expression, const std::string& hintRetVar);
llvm::Value* compileIf(const Expression& exprIf, const std::string& ident);
llvm::Value* compileSwitch(const Expression& exprSwitch, const std::string& hintRetVar);
llvm::Value* compileSwitchVariant(const Expression& exprSwitch, const std::string& hintRetVar);
llvm::Value* compileConstantStringAsPChar(const std::string &data, const std::string& hintRetVar);
llvm::Value* compileListAsSolidArray(const Expression &expr, const std::string& hintRetVar);
llvm::Value* compileSequence(const Expression &expr);
private:
compilation::Context context;
llvm::IntegerType* const tyNum;
};
}}
#endif /* INSTRUCTIONSADVANCED_H */
diff --git a/cpp/src/compilation/containers.cpp b/cpp/src/compilation/containers.cpp
index 9474f3b..f8d36fc 100644
--- a/cpp/src/compilation/containers.cpp
+++ b/cpp/src/compilation/containers.cpp
@@ -1,206 +1,206 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: containers.cpp
* Author: pgess <v.melnychenko@xreate.org>
*
* \file compilation/containers.h
* \brief Containers compilation support. See more [details on Containers](/w/concepts/containers)
*/
#include "compilation/containers.h"
using namespace std;
using namespace llvm;
using namespace xreate;
using namespace xreate::containers;
Iterator*
Iterator::create(xreate::compilation::Context context, const xreate::Symbol& var){
const Implementation& data = Query::queryImplementation(var);
switch(data.impl){
case ON_THE_FLY:
return new IteratorForward<ON_THE_FLY>(context, var, data.extract<ON_THE_FLY>());
case SOLID:
return new IteratorForward<SOLID>(context, var, data.extract<SOLID>());
default: assert(true);
}
assert(false && "Unknown declaration");
return nullptr;
}
llvm::Value*
IteratorForward<ON_THE_FLY>::begin() {
switch(sourceDecl.op) {
case xreate::Operator::LIST:
{
- sourceRawType = llvm::Type::getInt32Ty(llvm::getGlobalContext());
- return llvm::ConstantInt::get(Type::getInt32Ty(llvm::getGlobalContext()), 0);
+ sourceRawType = llvm::Type::getInt32Ty(llvm->llvmContext);
+ return llvm::ConstantInt::get(Type::getInt32Ty(llvm->llvmContext), 0);
};
case xreate::Operator::LIST_RANGE:{
assert(sourceDecl.operands.size()==2);
llvm::Value* result = sourceUnit->process(sourceDecl.operands.at(0));
sourceRawType = result->getType();
return result;
};
default: break;
}
if (linkedlist){
llvm::Value* result = sourceUnit->process(sourceDecl);
sourceRawType = result->getType();
return result;
}
assert(false);
}
llvm::Value*
IteratorForward<ON_THE_FLY>::end(){
switch(sourceDecl.op) {
case xreate::Operator::LIST: {
size_t idLast = sourceDecl.operands.size() - 1;
return ConstantInt::get(sourceRawType, idLast);
}
case xreate::Operator::LIST_RANGE: {
assert(sourceDecl.operands.size() == 2);
llvm::Value* valueEndOfRange = sourceUnit->process(sourceDecl.operands.at(1));
- llvm::Value* valueConstOne = llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), 1);
+ llvm::Value* valueConstOne = llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm->llvmContext), 1);
return llvm->builder.CreateAdd(valueEndOfRange, valueConstOne);
};
default: break;
}
//return null pointer
if (linkedlist){
return ConstantPointerNull::getNullValue(sourceRawType);
}
assert(false && "Unknown declaration");
return nullptr;
}
llvm::Value*
IteratorForward<ON_THE_FLY>::get(Value* index,const std::string& hintRetVar){
const Expression& currentDecl = CodeScope::getDefinition(current);
switch (currentDecl.op) {
case xreate::Operator::LIST: {
//TODO re check is it right scope(source) to compile currentDecl. Provide unittests.
llvm::Value* currentValue = sourceUnit->processSymbol(current);
return xreate::compilation::AdvancedInstructions(context).compileArrayIndex(currentValue, std::vector<Value *>{index});
};
case xreate::Operator::LIST_RANGE: {
return index;
};
case xreate::Operator::MAP: {
assert(currentDecl.getOperands().size()==1);
assert(currentDecl.bindings.size());
assert(currentDecl.blocks.size());
CodeScope* scopeLoop = currentDecl.blocks.front();
std::string varEl = currentDecl.bindings[0];
const Symbol& symbIn = Attachments::get<IdentifierSymbol>(currentDecl.getOperands()[0]);
auto it = std::unique_ptr<Iterator>(Iterator::create(context, symbIn));
Value* elIn = it->get(index, varEl);
compilation::ICodeScopeUnit* unitLoop = function->getScopeUnit(scopeLoop);
unitLoop->bindArg(elIn, std::move(varEl));
return unitLoop->compile();
}
case xreate::Operator::INVALID: {
//TODO review iterator determination strategy for case of Expression::BINDING
assert(currentDecl.__state==Expression::IDENT);
const Symbol& symbIn = Attachments::get<IdentifierSymbol>(currentDecl);
auto it = std::unique_ptr<Iterator>(Iterator::create(context, symbIn));
return it->get(index);
};
default: break;
}
if (linkedlist){
return index;
}
assert(false && "Unknown declaration");
return nullptr;
}
llvm::Value*
IteratorForward<ON_THE_FLY>::advance(Value* index, const std::string& hintRetVar){
switch(sourceDecl.op)
{
case xreate::Operator::LIST:
case xreate::Operator::LIST_RANGE:
- return llvm->builder.CreateAdd(index, llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), 1), hintRetVar);
+ return llvm->builder.CreateAdd(index, llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm->llvmContext), 1), hintRetVar);
default: break;
}
if (linkedlist){
ExpandedType tySource = llvm->ast->getType(CodeScope::getDefinition(source));
assert(tySource->__operator == TypeOperator::LIST && "Linked list implementation has to have ARRAY type");
assert(tySource->__operands.size());
return xreate::compilation::AdvancedInstructions(context).compileStructIndex(index, ExpandedType(TypeAnnotation(tySource->__operands.at(0))), linkedlist.fieldPointer);
}
assert(false && "Unknown declaration");
return nullptr;
}
//const ImplementationRec<ON_THE_FLY>& implementation
IteratorForward<SOLID>::IteratorForward(const compilation::Context& ctx, const xreate::Symbol& symbolContainer, const ImplementationRec<SOLID>& implementation)
: Iterator(), __length(implementation.size), llvm(ctx.pass->man->llvm)
{
__container = ctx.function->getScopeUnit(symbolContainer.scope)->processSymbol(symbolContainer);
}
llvm::Value*
IteratorForward<SOLID>::begin(){
//0
- return llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), 0);
+ return llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm->llvmContext), 0);
}
llvm::Value*
IteratorForward<SOLID>::end(){
//length
- return llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), __length);
+ return llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm->llvmContext), __length);
}
llvm::Value*
IteratorForward<SOLID>::get(llvm::Value* index,const std::string& hintRetVar){
//GEP[index]]
- llvm::Type* tyNum = llvm::Type::getInt32Ty(llvm::getGlobalContext());
+ llvm::Type* tyNum = llvm::Type::getInt32Ty(llvm->llvmContext);
llvm::Value* pResult = llvm->builder.CreateGEP(__container, ArrayRef<Value *>(std::vector<Value*>{ConstantInt::get(tyNum, 0), index}));
return llvm->builder.CreateLoad(pResult, hintRetVar);
}
llvm::Value*
IteratorForward<SOLID>::advance(llvm::Value* index, const std::string& hintRetVar){
//index + 1
- llvm::Type* tyNum = llvm::Type::getInt32Ty(llvm::getGlobalContext());
+ llvm::Type* tyNum = llvm::Type::getInt32Ty(llvm->llvmContext);
return llvm->builder.CreateAdd(index, llvm::ConstantInt::get(tyNum, 1), hintRetVar);
}
diff --git a/cpp/src/compilation/latereasoning.cpp b/cpp/src/compilation/latereasoning.cpp
new file mode 100644
index 0000000..496a97c
--- /dev/null
+++ b/cpp/src/compilation/latereasoning.cpp
@@ -0,0 +1,53 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * latereasoning.cpp
+ *
+ * Author: pgess <v.melnychenko@xreate.org>
+ * Created on May 26, 2018, 3:54 PM
+ */
+
+#include "compilation/latereasoning.h"
+
+namespace xreate{ namespace latereasoning {
+
+llvm::Value*
+LateReasoningCompiler::compile(const Expression& expr, const std::string& identHint){
+// #define HINT(x) (identHint.empty()? x : hintRetVar)
+//
+// LLVMLayer* llvm = context.pass->man->llvm;
+// compilation::ICodeScopeUnit* scope = context.scope;
+// AST* root = context.pass->man->root;
+// llvm::IRBuilder<>& builder = llvm->builder;
+//
+// const ExpandedType& typCondition = root->getType(expr.operands.at(0));
+// const int countVariants = typCondition->fields.size();
+//
+// llvm::Value * conditionRaw = scope->process(expr.operands.at(0));
+// llvm::Value* variantRaw = builder.CreateExtractValue(conditionRaw, llvm::ArrayRef<unsigned>({0}));
+// llvm::SwitchInst * instructionSwitch = builder.CreateSwitch(variantRaw, nullptr, countVariants);
+// //llvm::BasicBlock* blockProlog = builder.GetInsertBlock();
+//
+// llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm::getGlobalContext(), "switchLateAfter", function->raw);
+// builder.SetInsertPoint(blockEpilog);
+// llvm::Type* exprSwitchType = llvm->toLLVMType(root->getType(expr));
+// llvm::PHINode *ret = builder.CreatePHI(exprSwitchType, countVariants, HINT("switchLate"));
+// //builder.SetInsertPoint(blockProlog);
+//
+// for (int variantId = 0; variantId<countVariants; ++variantId){
+// llvm::BasicBlock *blockCase = llvm::BasicBlock::Create(llvm::getGlobalContext(),
+// "case" + std::to_string(i), function->raw);
+// builder.SetInsertPoint(blockCase);
+// CodeScope scopeBody = function->getScopeUnit(exp.blocks.back());
+// scopeBody->reset();
+//
+// llvm::Value* resultCase = scopeBody->compile();
+// ret->addIncoming(resultCase, builder.GetInsertBlock());
+// instructionSwitch->addCase(dyn_cast<llvm::ConstantInt>(llvm::ConstantInt::get(typI8, variantId), blockCase);
+//
+// builder.CreateBr(blockEpilog);
+// }
+}
+}}
\ No newline at end of file
diff --git a/cpp/src/compilation/latereasoning.h b/cpp/src/compilation/latereasoning.h
new file mode 100644
index 0000000..8a7be74
--- /dev/null
+++ b/cpp/src/compilation/latereasoning.h
@@ -0,0 +1,33 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * File: latereasoning.h
+ * Author: pgess <v.melnychenko@xreate.org>
+ *
+ * Created on May 26, 2018, 3:44 PM
+ */
+
+#ifndef LATEREASONING_H
+#define LATEREASONING_H
+
+#include "ast.h"
+#include "pass/compilepass.h"
+#include "llvmlayer.h"
+
+namespace xreate{ namespace latereasoning {
+
+class LateReasoningCompiler {
+public:
+ LateReasoningCompiler(compilation::Context ctx): context(ctx){}
+ llvm::Value* compile(const Expression& expr, const std::string& identHint);
+
+private:
+ compilation::Context context;
+};
+
+}}
+
+#endif /* LATEREASONING_H */
+
diff --git a/cpp/src/compilation/polymorph.h b/cpp/src/compilation/polymorph.h
index 743dcda..7088afe 100644
--- a/cpp/src/compilation/polymorph.h
+++ b/cpp/src/compilation/polymorph.h
@@ -1,64 +1,64 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: polymorphcompiler.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on October 7, 2017
*/
#ifndef POLYMORPHCOMPILER_H
#define POLYMORPHCOMPILER_H
#include "pass/compilepass.h"
#include "query/polymorph.h"
namespace xreate { namespace polymorph {
typedef Expression Guard;
template <class Parent>
class PolymorphCodeScopeUnit: public Parent{
public:
PolymorphCodeScopeUnit(const CodeScope* const codeScope, compilation::IFunctionUnit* f, CompilePass* compilePass)
: Parent(codeScope, f, compilePass) {}
protected:
compilation::ICallStatement* findFunction(const Expression& opCall) override {
//Check does invocation require guards
const std::string& nameCallee = opCall.getValueString();
const std::list<ManagedFnPtr>& specializations = Parent::pass->man->root->getFunctionSpecializations(nameCallee);
//Extern function
if (specializations.size() == 0){
return Parent::findFunction(opCall);
}
//No other specializations. Check if it has no guard
if (specializations.size() == 1){
if (!specializations.front()->guard.isValid()) {
return Parent::findFunction(opCall);
}
}
//Several specializations
- PolymorphQuery* query = dynamic_cast<PolymorphQuery*>(Parent::pass->man->clasp->getQuery(QueryId::PolymorphQuery));
+ PolymorphQuery* query = dynamic_cast<PolymorphQuery*>(Parent::pass->man->transcend->getQuery(QueryId::PolymorphQuery));
const Expression& guardSelected = query->get(opCall);
std::map<Guard, ManagedFnPtr> indexSpecs;
for(ManagedFnPtr specialization: specializations){
indexSpecs.emplace(specialization->guard, specialization);
}
assert(indexSpecs.count(guardSelected) && "Can't find appropriate guard");
return new compilation::CallStatementRaw(Parent::pass->getFunctionUnit(indexSpecs.at(guardSelected))->compile(), Parent::pass->man->llvm);
}
};
} } //end of xreate::polymorph
#endif /* POLYMORPHCOMPILER_H */
diff --git a/cpp/src/compilation/targetinterpretation.cpp b/cpp/src/compilation/targetinterpretation.cpp
index ccd5f02..9d7d29d 100644
--- a/cpp/src/compilation/targetinterpretation.cpp
+++ b/cpp/src/compilation/targetinterpretation.cpp
@@ -1,645 +1,645 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: targetinterpretation.cpp
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on June 29, 2016, 6:45 PM
*/
/**
* \file targetinterpretation.h
* \brief Interpretation support. See more [details on Interpretation](/w/concepts/dsl/)
*/
#include "compilation/targetinterpretation.h"
#include "pass/interpretationpass.h"
#include "analysis/typeinference.h"
#include "llvmlayer.h"
#include "compilation/scopedecorators.h"
#include <boost/scoped_ptr.hpp>
#include <iostream>
#include <clang/AST/DeclBase.h>
#include <csignal>
using namespace std;
using namespace xreate::compilation;
namespace xreate{ namespace interpretation{
const Expression EXPRESSION_FALSE = Expression(Atom<Number_t>(0));
const Expression EXPRESSION_TRUE = Expression(Atom<Number_t>(1));
Expression
representAsAnnotation(const Gringo::Symbol& atom){
switch (atom.type()) {
case Gringo::SymbolType::Num: {
Expression result(Operator::VARIANT, {Expression(atom.num())});
result.setValueDouble(0);
return result;
}
case Gringo::SymbolType::Str: {
Expression result(Operator::VARIANT, {Expression(Atom<String_t>(std::string(atom.string().c_str())))});
result.setValueDouble(1);
return result;
}
case Gringo::SymbolType::Fun: {
Expression fnDescription(Operator::LIST_NAMED, {});
std::list<Atom<Identifier_t>> bindings{Atom<Identifier_t>("name"), Atom<Identifier_t>("arguments")};
fnDescription.addBindings(bindings.begin(), bindings.end());
fnDescription.addArg(Expression(Atom<String_t>(std::string(atom.name().c_str()))));
Expression args(Operator::LIST, {});
for (const Gringo::Symbol& arg : atom.args()) {
args.addArg(representAsAnnotation(arg));
}
fnDescription.addArg(std::move(args));
Expression result(Operator::VARIANT, {fnDescription});
result.setValueDouble(2);
return result;
}
default: {
assert(false);
}
}
}
CodeScope*
InterpretationScope::processOperatorIf(const Expression& expression){
const Expression& exprCondition = process(expression.getOperands()[0]);
if (exprCondition == EXPRESSION_TRUE){
return expression.blocks.front();
}
return expression.blocks.back();
}
CodeScope*
InterpretationScope::processOperatorSwitch(const Expression& expression) {
const Expression& exprCondition = process(expression.operands[0]);
bool flagHasDefault = expression.operands[1].op == Operator::CASE_DEFAULT;
//TODO check that one and only one case variant is appropriate
for (size_t size = expression.operands.size(), i= flagHasDefault? 2: 1; i<size; ++i){
const Expression& exprCase = process(expression.operands[i]);
if (function->getScope((const CodeScope*) exprCase.blocks.front())->processScope() == exprCondition){
return exprCase.blocks.back();
}
}
if (flagHasDefault){
const Expression& exprCaseDefault = expression.operands[1];
return exprCaseDefault.blocks.front();
}
assert(false && "Switch has no appropriate variant");
return nullptr;
}
CodeScope*
InterpretationScope::processOperatorSwitchVariant(const Expression& expression){
const Expression& condition = process(expression.operands.at(0));
assert(condition.op == Operator::VARIANT);
const string& identCondition = expression.bindings.front();
Expression opExpected(Atom<Number_t>(condition.getValueDouble()));
auto itFoundValue = std::find(++expression.operands.begin(), expression.operands.end(), opExpected);
assert(itFoundValue != expression.operands.end());
int indexBlock = itFoundValue - expression.operands.begin() -1;
auto blockFound = expression.blocks.begin();
std::advance(blockFound, indexBlock);
InterpretationScope* scopeI12n = function->getScope(*blockFound);
if(condition.operands.size()){
const Expression& value=condition.operands.at(0);
scopeI12n->overrideBindings({
{value, identCondition}});
}
return *blockFound;
}
llvm::Value*
InterpretationScope::compileHybrid(const InterpretationOperator& op, const Expression& expression, const Context& context){
switch(op){
case IF_INTERPRET_CONDITION: {
CodeScope* scopeResult = processOperatorIf(expression);
llvm::Value* result = context.function->getScopeUnit(scopeResult)->compile();
return result;
}
case SWITCH_INTERPRET_CONDITION:{
CodeScope* scopeResult = processOperatorSwitch(expression);
llvm::Value* result = context.function->getScopeUnit(scopeResult)->compile();
return result;
}
case SWITCH_VARIANT: {
CodeScope* scopeResult = processOperatorSwitchVariant(expression);
const Expression& condition = expression.operands.at(0);
const Expression& valueCondition = process(condition);
const string identCondition = expression.bindings.front();
auto scopeCompilation = Decorators<CachedScopeDecoratorTag>::getInterface(context.function->getScopeUnit(scopeResult));
if(valueCondition.operands.size()){
//override value
Symbol symbCondition{ScopedSymbol{scopeResult->__identifiers.at(identCondition), versions::VERSION_NONE}, scopeResult};
scopeCompilation->overrideDeclarations(
{{symbCondition, Expression(valueCondition.operands.at(0))}}
);
//set correct type for binding:
TypeAnnotation typeVariant = typeinference::getType(condition, *function->man->ast);
int conditionIndex = valueCondition.getValueDouble();
ScopedSymbol symbolInternal = scopeResult->getSymbol(identCondition);
scopeResult->__declarations[symbolInternal].bindType(typeVariant.__operands.at(conditionIndex));
}
llvm::Value* result = context.function->getScopeUnit(scopeResult)->compile();
return result;
}
case FOLD_INTERPRET_INPUT: {
//initialization
const Expression& exprInput = process(expression.getOperands()[0]);
assert(exprInput.op == Operator::LIST);
CodeScope* scopeBody = expression.blocks.front();
const string& nameEl = expression.bindings[0];
Symbol symbEl{ScopedSymbol{scopeBody->__identifiers.at(nameEl), versions::VERSION_NONE}, scopeBody};
const std::string& idAccum = expression.bindings[1];
llvm::Value* rawAccum = context.scope->process(expression.getOperands()[1]);
InterpretationScope* intrBody = function->getScope(scopeBody);
auto unitBody = Decorators<CachedScopeDecoratorTag>::getInterface(context.function->getScopeUnit(scopeBody));
const std::vector<Expression> elementsInput= exprInput.getOperands();
for(size_t i=0; i<elementsInput.size(); ++i) {
const Expression& exprElement=elementsInput[i];
intrBody->overrideBindings({
{exprElement, nameEl}});
unitBody->overrideDeclarations({
{symbEl, exprElement}}); //resets unitBody
unitBody->bindArg(rawAccum, string(idAccum));
rawAccum=unitBody->compile();
}
return rawAccum;
}
/*
case FOLD_INF_INTERPRET_INOUT{
}
*/
//TODO refactor as InterpretationCallStatement class
case CALL_INTERPRET_PARTIAL: {
const std::string &calleeName = expression.getValueString();
ICodeScopeUnit* scopeUnitSelf = context.scope;
ManagedFnPtr callee = this->function->man->ast->findFunction(calleeName);
const FunctionInterpretationData& calleeData = FunctionInterpretationHelper::getSignature(callee);
std::vector<llvm::Value *> argsActual;
PIFSignature sig;
sig.declaration = callee;
for(size_t no=0, size = expression.operands.size(); no < size; ++no){
const Expression& op = expression.operands[no];
if (calleeData.signature.at(no) == INTR_ONLY){
sig.bindings.push_back(process(op));
continue;
}
argsActual.push_back(scopeUnitSelf->process(op));
}
TargetInterpretation* man = dynamic_cast<TargetInterpretation*>(this->function->man);
PIFunction* pifunction = man->getFunction(move(sig));
llvm::Function* raw = pifunction->compile();
boost::scoped_ptr<CallStatementRaw> statement(new CallStatementRaw(raw, man->pass->man->llvm));
return (*statement)(move(argsActual));
}
default: break;
}
assert(false&& "Unknown hybrid operator");
return nullptr;
}
llvm::Value*
InterpretationScope::compile(const Expression& expression, const Context& context){
const InterpretationData& data = Attachments::get<InterpretationData>(expression);
if (data.op != InterpretationOperator::NONE){
return compileHybrid(data.op, expression, context);
}
Expression result = process(expression);
return context.scope->process(result);
}
Expression
InterpretationScope::process(const Expression& expression) {
#ifndef NDEBUG
if (expression.tags.count("bpoint")){
std::raise(SIGINT);
}
#endif
PassManager* man = (static_cast<TargetInterpretation*> (function->man))->pass->man;
switch (expression.__state){
case Expression::INVALID:
assert(false);
case Expression::NUMBER:
case Expression::STRING:
return expression;
case Expression::IDENT:{
Symbol s = Attachments::get<IdentifierSymbol>(expression);
return Parent::processSymbol(s);
}
case Expression::COMPOUND:
break;
default: assert(false);
}
switch (expression.op) {
case Operator::EQU: {
const Expression& left = process(expression.operands[0]);
const Expression& right = process(expression.operands[1]);
if (left == right) return EXPRESSION_TRUE;
return EXPRESSION_FALSE;
}
case Operator::NE: {
const Expression& left = process(expression.operands[0]);
const Expression& right = process(expression.operands[1]);
if (left == right) return EXPRESSION_FALSE;
return EXPRESSION_TRUE;
}
case Operator::LOGIC_AND: {
assert(expression.operands.size() == 1);
return process (expression.operands[0]);
}
// case Operator::LOGIC_OR:
case Operator::CALL: {
const std::string &fnName = expression.getValueString();
ManagedFnPtr fnAst = this->function->man->ast->findFunction(fnName);
InterpretationFunction* fnUnit = this->function->man->getFunction(fnAst);
vector<Expression> args;
args.reserve(expression.getOperands().size());
for(size_t i=0, size = expression.getOperands().size(); i<size; ++i) {
args.push_back(process(expression.getOperands()[i]));
}
return fnUnit->process(args);
}
case Operator::CALL_INTRINSIC: {
std::string nameFunction = expression.getValueString();
if(nameFunction=="query"){
assert(expression.operands.size() == 1);
assert(expression.operands.front().__state == Expression::STRING);
std::string namePredicate = expression.operands.front().getValueString();
- StaticModel model = (static_cast<TargetInterpretation*>(function->man))->pass->man->clasp->query(namePredicate);
+ StaticModel model = (static_cast<TargetInterpretation*>(function->man))->pass->man->transcend->query(namePredicate);
Expression result(Operator::LIST, {});
if(model.size())
for (const auto& row: model) {
result.addArg(representAsAnnotation(std::get<1>(row)));
}
return result;
} else if(nameFunction=="query_scope"){
- ScopePacked scopeId = man->clasp->pack(scope);
+ ScopePacked scopeId = man->transcend->pack(scope);
Expression result(Operator::VARIANT, {Expression(scopeId)});
result.setValueDouble(0);
return result;
} else {
assert(false && "Unknown intrinsic");
}
}
case Operator::IF:{
CodeScope* scopeResult = processOperatorIf(expression);
return function->getScope(scopeResult)->processScope();
}
case Operator::SWITCH: {
CodeScope* scopeResult = processOperatorSwitch(expression);
return function->getScope(scopeResult)->processScope();
}
case Operator::SWITCH_VARIANT: {
CodeScope* scopeResult = processOperatorSwitchVariant(expression);
return function->getScope(scopeResult)->processScope();
}
case Operator::VARIANT: {
if(!expression.operands.size()) return expression;
Expression variantData = process(expression.operands[0]);
Expression result{Operator::VARIANT, {variantData}};
result.setValueDouble(expression.getValueDouble());
return result;
}
case Operator::INDEX: {
Expression exprData = process(expression.operands[0]);
for (size_t keyId=1; keyId<expression.operands.size(); ++keyId){
const Expression& exprKey = process(expression.operands[keyId]);
if (exprKey.__state == Expression::STRING){
const string& key = exprKey.getValueString();
assert(exprData.__indexBindings.count(key));
size_t idxKey = exprData.__indexBindings.at(key);
exprData = Expression(exprData.operands.at(idxKey));
continue;
}
if (exprKey.__state == Expression::NUMBER){
int key = exprKey.getValueDouble();
exprData = Expression(exprData.operands[key]);
continue;
}
assert(false && "Inappropriate key");
}
return exprData;
}
case Operator::FOLD: {
const Expression& exprInput = process(expression.getOperands()[0]);
const Expression& exprInit = process(expression.getOperands()[1]);
const std::string& argEl = expression.bindings[0];
const std::string& argAccum = expression.bindings[1];
InterpretationScope* body = function->getScope(expression.blocks.front());
Expression accum = exprInit;
for(size_t size=exprInput.getOperands().size(), i=0; i<size; ++i){
body->overrideBindings({
{exprInput.getOperands()[i], argEl},
{accum, argAccum}
});
accum = body->processScope();
}
return accum;
}
case Operator::LIST:
case Operator::LIST_NAMED:
case Operator::LIST_RANGE:
{
Expression result(expression.op,{});
result.operands.resize(expression.operands.size());
result.bindings=expression.bindings;
result.__indexBindings=expression.__indexBindings;
int keyId=0;
for(const Expression& opCurrent : expression.operands) {
result.operands[keyId++]=process(opCurrent);
}
return result;
}
// case Operator::MAP: {
// break;
// }
default: break;
}
return expression;
}
InterpretationFunction*
TargetInterpretation::getFunction(IFunctionUnit* unit){
if (__dictFunctionsByUnit.count(unit)) {
return __dictFunctionsByUnit.at(unit);
}
InterpretationFunction* f = new InterpretationFunction(unit->function, this);
__dictFunctionsByUnit.emplace(unit, f);
assert(__functions.emplace(unit->function.id(), f).second);
return f;
}
PIFunction*
TargetInterpretation::getFunction(PIFSignature&& sig){
auto f = __pifunctions.find(sig);
if (f != __pifunctions.end()){
return f->second;
}
PIFunction* result = new PIFunction(PIFSignature(sig), __pifunctions.size(), this);
__pifunctions.emplace(move(sig), result);
assert(__dictFunctionsByUnit.emplace(result->functionUnit, result).second);
return result;
}
InterpretationScope*
TargetInterpretation::transformContext(const Context& c){
return this->getFunction(c.function)->getScope(c.scope->scope);
}
llvm::Value*
TargetInterpretation::compile(const Expression& expression, const Context& ctx){
return transformContext(ctx)->compile(expression, ctx);
}
InterpretationFunction::InterpretationFunction(const ManagedFnPtr& function, Target<TargetInterpretation>* target)
: Function<TargetInterpretation>(function, target)
{}
Expression
InterpretationFunction::process(const std::vector<Expression>& args){
InterpretationScope* body = getScope(__function->__entry);
list<pair<Expression, string>> bindings;
for(size_t i=0, size=args.size(); i<size; ++i) {
bindings.push_back(make_pair(args.at(i), body->scope->__bindings.at(i)));
}
body->overrideBindings(bindings);
return body->processScope();
}
// Partial function interpretation
typedef BasicFunctionUnit PIFunctionUnitParent;
class PIFunctionUnit : public PIFunctionUnitParent {
public:
PIFunctionUnit(ManagedFnPtr f, std::set<size_t>&& arguments, size_t id, CompilePass* p)
: PIFunctionUnitParent(f, p), argumentsActual(move(arguments)), __id(id) { }
protected:
std::vector<llvm::Type*> prepareArguments(){
LLVMLayer* llvm = PIFunctionUnitParent::pass->man->llvm;
AST* ast = PIFunctionUnitParent::pass->man->root;
CodeScope* entry = PIFunctionUnitParent::function->__entry;
std::vector<llvm::Type*> signature;
for(size_t no: argumentsActual){
VNameId argId = entry->__identifiers.at(entry->__bindings.at(no));
ScopedSymbol arg{argId, versions::VERSION_NONE};
signature.push_back(llvm->toLLVMType(ast->expandType(entry->__declarations.at(arg).type)));
}
return signature;
}
llvm::Function::arg_iterator prepareBindings(){
CodeScope* entry = PIFunctionUnitParent::function->__entry;
ICodeScopeUnit* entryCompilation = PIFunctionUnitParent::getScopeUnit(entry);
llvm::Function::arg_iterator fargsI = PIFunctionUnitParent::raw->arg_begin();
for(size_t no: argumentsActual){
ScopedSymbol arg{entry->__identifiers.at(entry->__bindings.at(no)), versions::VERSION_NONE};
entryCompilation->bindArg(&*fargsI, arg);
fargsI->setName(entry->__bindings.at(no));
++fargsI;
}
return fargsI;
}
virtual std::string prepareName(){
return PIFunctionUnitParent::prepareName() + "_" + std::to_string(__id);
}
private:
std::set<size_t> argumentsActual;
size_t __id;
};
PIFunction::PIFunction(PIFSignature&& sig, size_t id, TargetInterpretation* target)
: InterpretationFunction(sig.declaration, target), signatureInstance(move(sig)) {
const FunctionInterpretationData& functionData = FunctionInterpretationHelper::getSignature(signatureInstance.declaration);
std::set<size_t> argumentsActual;
for (size_t no=0, size=functionData.signature.size(); no < size; ++no){
if (functionData.signature.at(no) != INTR_ONLY){
argumentsActual.insert(no);
}
}
functionUnit = new PIFunctionUnit(signatureInstance.declaration, move(argumentsActual), id, target->pass);
CodeScope* entry = signatureInstance.declaration->__entry;
auto entryUnit = Decorators<CachedScopeDecoratorTag>::getInterface<>(functionUnit->getEntry());
InterpretationScope* entryIntrp = InterpretationFunction::getScope(entry);
list<pair<Expression, std::string>> bindingsPartial;
list<pair<Symbol, Expression>> declsPartial;
for(size_t no=0, sigNo=0, size=entry->__bindings.size(); no<size; ++no) {
if(functionData.signature.at(no)==INTR_ONLY){
bindingsPartial.push_back({signatureInstance.bindings[sigNo], entry->__bindings[no]});
VNameId argId=entry->__identifiers.at(entry->__bindings[no]);
Symbol argSymbol{ScopedSymbol
{argId, versions::VERSION_NONE}, entry};
declsPartial.push_back({argSymbol, signatureInstance.bindings[sigNo]});
++sigNo;
}
}
entryIntrp->overrideBindings(bindingsPartial);
entryUnit->overrideDeclarations(declsPartial);
}
llvm::Function*
PIFunction::compile(){
llvm::Function* raw = functionUnit->compile();
return raw;
}
bool operator<(const PIFSignature& lhs, const PIFSignature& rhs){
if (lhs.declaration.id() != rhs.declaration.id()) {
return lhs.declaration.id() < rhs.declaration.id();
}
return lhs.bindings < rhs.bindings;
}
bool operator<(const PIFSignature& lhs, PIFunction* const rhs){
return lhs < rhs->signatureInstance;
}
bool operator<(PIFunction* const lhs, const PIFSignature& rhs){
return lhs->signatureInstance < rhs;
}
}}
/** \class xreate::interpretation::InterpretationFunction
*
* Holds list of xreate::interpretation::InterpretationScope 's focused on interpretation of individual code scopes
*
* There is particulat subclass PIFunction intended to represent partially interpreted functions
*\sa TargetInterpretation, [Interpretation Concept](/w/concepts/dfa)
*/
/** \class xreate::interpretation::TargetInterpretation
*
* Executed during compilation and intented to preprocess eligible parts of code.
* Established on [Targets Infrastructure](\ref compilation::Target)
*
* Holds list of InterpretationFunction / PIFunction to represent interpretation process for individual functions
*
* In order to be activated during compilation process there is
* InterpretationScopeDecorator implementation of ICodeScopeUnit
* \sa InterpretationPass, compilation::Target, [Interpretation Concept](/w/concepts/dfa)
*
- */
\ No newline at end of file
+ */
diff --git a/cpp/src/compilation/targetinterpretation.h b/cpp/src/compilation/targetinterpretation.h
index 567bf92..377993e 100644
--- a/cpp/src/compilation/targetinterpretation.h
+++ b/cpp/src/compilation/targetinterpretation.h
@@ -1,139 +1,139 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: targetstatic.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on July 2, 2016, 1:25 PM
*/
#ifndef TARGETSTATIC_H
#define TARGETSTATIC_H
#include "ast.h"
#include "pass/compilepass.h"
#include "compilation/targets.h"
#include "pass/interpretationpass.h"
-#include "clasplayer.h"
+#include "transcendlayer.h"
namespace xreate{ namespace interpretation{
class TargetInterpretation;
class InterpretationScope;
class InterpretationFunction;
}}
namespace xreate{ namespace compilation{
template <>
struct TargetInfo<interpretation::TargetInterpretation> {
typedef Expression Result;
typedef interpretation::InterpretationScope Scope;
typedef interpretation::InterpretationFunction Function;
};
}}
namespace xreate{ namespace interpretation{
/** \brief Encapsulates interpretation of a single Code Scope */
class InterpretationScope: public compilation::Scope<TargetInterpretation>{
typedef Scope<TargetInterpretation> Parent;
public:
InterpretationScope(const CodeScope* scope, compilation::Function<TargetInterpretation>* f): Parent(scope, f) {}
Expression process(const Expression& expression) override;
llvm::Value* compile(const Expression& expression, const compilation::Context& context);
private:
llvm::Value* compileHybrid(const InterpretationOperator& op, const Expression& expression, const compilation::Context& context);
//llvm::Value* compilePartialFnCall(const Expression& expression, const Context& context);
CodeScope* processOperatorIf(const Expression& expression);
CodeScope* processOperatorSwitch(const Expression& expression);
CodeScope* processOperatorSwitchVariant(const Expression& expression);
};
/** \brief Encapsulates interpretation of a single %Function */
class InterpretationFunction: public compilation::Function<TargetInterpretation>{
public:
InterpretationFunction(const ManagedFnPtr& function, compilation::Target<TargetInterpretation>* target);
Expression process(const std::vector<Expression>& args);
};
/** \brief Signature of a partially interpreted function */
struct PIFSignature{
ManagedFnPtr declaration;
std::vector<Expression> bindings;
};
class PIFunctionUnit;
/** \brief Partially interpreted function */
class PIFunction: public InterpretationFunction{
public:
PIFunctionUnit* functionUnit;
PIFSignature signatureInstance;
PIFunction(PIFSignature&& sig, size_t id, TargetInterpretation* target);
llvm::Function* compile();
};
bool operator<(const PIFSignature& lhs, PIFunction* const rhs);
bool operator<(PIFunction* const lhs, const PIFSignature& rhs);
/** \brief Encapsulates actual [Interpretation](/w/concepts/dfa) based on InterpretationPass analysis results */
class TargetInterpretation: public compilation::Target<TargetInterpretation>{
public:
TargetInterpretation(AST* root, CompilePass* passCompilation): Target<TargetInterpretation>(root), pass(passCompilation){}
//target:
public:
InterpretationFunction* getFunction(compilation::IFunctionUnit* unit);
PIFunction* getFunction(PIFSignature&& sig);
private:
std::map<PIFSignature, PIFunction*> __pifunctions;
std::map<compilation::IFunctionUnit*, InterpretationFunction*> __dictFunctionsByUnit;
//self:
public:
CompilePass* pass;
llvm::Value* compile(const Expression& expression, const compilation::Context& ctx);
private:
InterpretationScope* transformContext(const compilation::Context& c);
};
/**\brief Interpretation-aware Code Scope decorator
* \extends xreate::compilation::ICodeScopeUnit
*/
template<class Parent>
class InterpretationScopeDecorator: public Parent{
public:
InterpretationScopeDecorator(const CodeScope* const codeScope, compilation::IFunctionUnit* f, CompilePass* compilePass): Parent(codeScope, f, compilePass){}
virtual llvm::Value* process(const Expression& expr, const std::string& hintVarDecl){
const InterpretationData& data = Attachments::get<InterpretationData>(expr, {ANY, NONE});
bool flagInterpretationEligible = (data.resolution == INTR_ONLY || data.op != InterpretationOperator::NONE);
if (flagInterpretationEligible){
compilation::Context ctx{this, this->function, this->pass};
return Parent::pass->targetInterpretation->compile(expr, ctx);
}
return Parent::process(expr, hintVarDecl);
}
};
/** \brief translates Logic expression(Gringo::Symbol) into Xreate expression to support intrinsic function `query` */
Expression representAsAnnotation(const Gringo::Symbol& symbol);
}} //end of xreate:: interpretation
#endif /* TARGETSTATIC_H */
//transformers:
// template<>
// struct TransformerInfo<TargetInterpretation> {
// static const int id = 1;
// };
diff --git a/cpp/src/compilation/transformersaturation.cpp b/cpp/src/compilation/transformersaturation.cpp
index 053c1d9..1411cca 100644
--- a/cpp/src/compilation/transformersaturation.cpp
+++ b/cpp/src/compilation/transformersaturation.cpp
@@ -1,85 +1,84 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* transformersaturation.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on March 25, 2017, 10:06 PM
*/
/**
* \file transformersaturation.h
* \brief Loop saturation support
*/
#include "transformersaturation.h"
#include "llvmlayer.h"
using namespace llvm;
namespace xreate { namespace compilation {
TransformerSaturation::TransformerSaturation(llvm::BasicBlock* allocationBlock, TransformationsManager* manager)
: man(manager), blockAllocation(allocationBlock){
- llvm::Type* tyInt1 = llvm::Type::getInt1Ty(llvm::getGlobalContext());
-
- constTrue = llvm::ConstantInt::get(tyInt1, 1);
- constFalse = llvm::ConstantInt::get(tyInt1, 0);
-
if (man->exists<TransformerSaturation>()){
oldInstance = man->update(this);
} else {
man->registerTransformer("break", this);
}
}
TransformerSaturation::~TransformerSaturation(){
if (oldInstance) {
man->update(oldInstance);
} else {
man->unregisterTransformer("break", this);
}
}
llvm::Value*
TransformerSaturation::transform(const Expression& expression, llvm::Value* raw, const Context& ctx){
processBreak(ctx);
return raw;
}
void
TransformerSaturation::processBreak(const Context& ctx){
allocateFlag(ctx);
//show the saturation flag
llvm::IRBuilder<>& builder = ctx.pass->man->llvm->builder;
+ llvm::Type* tyInt1 = llvm::Type::getInt1Ty(ctx.pass->man->llvm->llvmContext);
+ llvm::Constant* constTrue = llvm::ConstantInt::get(tyInt1, 1);
builder.CreateStore(constTrue, flagSaturation, true);
}
void
TransformerSaturation::allocateFlag(const Context& ctx){
//allocation of saturation flag
- llvm::Type* tyInt1 = llvm::Type::getInt1Ty(llvm::getGlobalContext());
IRBuilder<> builder(blockAllocation, blockAllocation->getFirstInsertionPt());
+ llvm::Type* tyInt1 = llvm::Type::getInt1Ty(ctx.pass->man->llvm->llvmContext);
+ llvm::Constant* constTrue = llvm::ConstantInt::get(tyInt1, 1);
flagSaturation = builder.CreateAlloca(tyInt1, constTrue, "flagSaturation");
+ llvm::Constant* constFalse = llvm::ConstantInt::get(tyInt1, 0);
builder.CreateStore(constFalse, flagSaturation, true);
}
bool
TransformerSaturation::insertSaturationChecks(llvm::BasicBlock* blockContinue, llvm::BasicBlock* blockExit, const Context& ctx){
if (!flagSaturation) return false;
llvm::IRBuilder<>& builder = ctx.pass->man->llvm->builder;
builder.CreateCondBr(builder.CreateLoad(flagSaturation), blockExit, blockContinue);
return true;
}
} }
diff --git a/cpp/src/compilation/transformersaturation.h b/cpp/src/compilation/transformersaturation.h
index c1a0075..bb370a1 100644
--- a/cpp/src/compilation/transformersaturation.h
+++ b/cpp/src/compilation/transformersaturation.h
@@ -1,49 +1,45 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: transformersaturation.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on March 25, 2017, 9:59 PM
*/
#ifndef TRANSFORMERSATURATION_H
#define TRANSFORMERSATURATION_H
#include "transformations.h"
namespace xreate { namespace compilation {
class TransformerSaturation: public Transformer{
public:
TransformerSaturation(llvm::BasicBlock* allocationBlock, TransformationsManager* manager);
~TransformerSaturation();
llvm::Value* transform(const Expression& expression, llvm::Value* raw, const Context& ctx) override;
void processBreak(const Context& ctx);
void allocateFlag(const Context& ctx);
bool insertSaturationChecks(llvm::BasicBlock* blockContinue, llvm::BasicBlock* blockExit, const Context& ctx);
private:
TransformationsManager* man;
TransformerSaturation* oldInstance = nullptr;
-
llvm::BasicBlock* blockAllocation;
-
- llvm::Value* constTrue;
- llvm::Value* constFalse;
llvm::Value* flagSaturation = nullptr;
};
template <>
struct TransformerInfo<TransformerSaturation> {
static const unsigned int id = 0;
};
} }
#endif /* TRANSFORMERSATURATION_H */
diff --git a/cpp/src/compilation/versions.h b/cpp/src/compilation/versions.h
index c448bde..3aeaab5 100644
--- a/cpp/src/compilation/versions.h
+++ b/cpp/src/compilation/versions.h
@@ -1,153 +1,155 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* versions.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on January 21, 2017, 1:24 PM
*/
/**
* \file
* \brief CodeScope's Decorator to support Versions
*/
#include "pass/versionspass.h"
#include "pass/compilepass.h"
#include "llvmlayer.h"
namespace xreate {
class CompilePass;
namespace compilation {
class ICodeScopeUnit;
class IFunctionUnit;
}
namespace versions{
/**\brief Enables compilation of code with versioned variables
* \details Dictates order of computation determined by VersionsPass
* \extends xreate::compilation::ICodeScopeUnit
* \sa VersionsPass, VersionsGraph
*/
template<class Parent>
class VersionsScopeDecorator: public Parent{
typedef VersionsScopeDecorator<Parent> SELF;
public:
VersionsScopeDecorator(const CodeScope* const codeScope, compilation::IFunctionUnit* f, CompilePass* compilePass): Parent(codeScope, f, compilePass){}
virtual llvm::Value* processSymbol(const Symbol& s, std::string hintSymbol=""){
if (Attachments::exists<VersionImposedDependency>(s)){
const std::list<Symbol> dependencies = Attachments::get<VersionImposedDependency>(s);
for(const Symbol& symbolDependent: dependencies){
processSymbol(symbolDependent);
}
}
llvm::Value* result = Parent::processSymbol(s, hintSymbol);
if (s.identifier.version == VERSION_INIT){
llvm::Value* storage = SELF::processIntrinsicInit(result->getType(), hintSymbol);
setSymbolStorage(s, storage);
processIntrinsicCopy(result, storage);
return compilation::ICodeScopeUnit::pass->man->llvm->builder.CreateLoad(storage);
} else if (s.identifier.version != VERSION_NONE){
Symbol symbolInitVersion = getSymbolInitVersion(s);
llvm::Value* storage = getSymbolStorage(symbolInitVersion);
processIntrinsicCopy(result, storage);
return compilation::ICodeScopeUnit::pass->man->llvm->builder.CreateLoad(storage);
}
return result;
}
llvm::Value*
processIntrinsicInit(llvm::Type* typeStorage, const std::string& hintVarDecl=""){
- llvm::IntegerType* tyInt = llvm::Type::getInt32Ty(llvm::getGlobalContext());
+ LLVMLayer* llvm = compilation::ICodeScopeUnit::pass->man->llvm;
+
+ llvm::IntegerType* tyInt = llvm::Type::getInt32Ty(llvm->llvmContext);
llvm::ConstantInt* constOne = llvm::ConstantInt::get(tyInt, 1, false);
- return compilation::ICodeScopeUnit::pass->man->llvm->builder.CreateAlloca(typeStorage, constOne, hintVarDecl);
+ return llvm->builder.CreateAlloca(typeStorage, constOne, hintVarDecl);
}
void
processIntrinsicCopy(llvm::Value* value, llvm::Value* storage){
compilation::ICodeScopeUnit::pass->man->llvm->builder.CreateStore(value, storage);
}
private:
std::map<Symbol, llvm::Value*> __symbolStorage;
static Symbol
getSymbolInitVersion(const Symbol& s){
return Symbol{ScopedSymbol{s.identifier.id, VERSION_INIT}, s.scope};
}
llvm::Value*
getSymbolStorage(const Symbol& s){
return __symbolStorage.at(s);
}
void setSymbolStorage(const Symbol& s, llvm::Value* storage){
__symbolStorage[s] = storage;
}
};
template<class Parent>
class VersionedFunctionDecorator : public Parent {
public:
VersionedFunctionDecorator(ManagedFnPtr f, CompilePass* p)
: Parent(f, p){}
protected:
std::vector<llvm::Type*> prepareArguments() {
std::vector<llvm::Type*>&& arguments = Parent::prepareArguments();
return arguments;
}
};
} } //end of namespace xreate::versions
// llvm::Value*
// processIntrinsicInitAndCopy(){
//
// }
//llvm::Value*
//process(const Expression& expr, const std::string& hintVarDecl){
// case Operator::CALL_INTRINSIC: {
// enum INRINSIC{INIT, COPY};
//
// const ExpandedType& typSymbol = pass->man->root->expandType(expr.type);
//
// INTRINSIC op = (INTRINSIC) expr.getValueDouble();
//
// switch (op){
// case INIT: {
// llvm::Type* typSymbolRaw = l.toLLVMType(typSymbol);
//
//
// return storage;
// }
//
// case COPY: {
// llvm::Type* typSymbolRaw = l.toLLVMType(typSymbol);
// llvm::value* valueOriginal = process(expr.getOperands()[0], hintVarDecl);
// llvm::Value* storage = l.builder.CreateAlloca(typSymbolRaw, constOne, hintVarDecl);
// llvm::Value* valueCopy = l.builder.CreateStore(valueOriginal, storage);
//
// return valueCopy;
// }
// }
// return;
// }
//}
//};
diff --git a/cpp/src/contextrule.cpp b/cpp/src/contextrule.cpp
index 7bdcb9e..a24d528 100644
--- a/cpp/src/contextrule.cpp
+++ b/cpp/src/contextrule.cpp
@@ -1,61 +1,61 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* contextrule.cpp
*
* Created on: Jan 2, 2016
* Author: pgess <v.melnychenko@xreate.org>
*/
/**
* \file contextrule.h
* \brief Context rules support. See more on [context rules](/w/concepts/context#context-rules)
*/
#include "contextrule.h"
-#include "clasplayer.h"
+#include "transcendlayer.h"
#include "analysis/utils.h"
#include <boost/format.hpp>
using namespace xreate;
using namespace std;
ContextRule::ContextRule(const Expression& rule) {
assert(rule.op == Operator::CONTEXT_RULE);
assert(rule.operands.size() == 3);
head = rule.operands.at(0);
guards = rule.operands.at(1);
body = rule.operands.at(2);
}
std::string
ContextRule::compile(const ScopePacked& scopeId) const{
const string prolog =
" %context rule visibility implemenetation\n"
"context_rule_visibility(X, Y) :- X=Y, scope(X), scope(Y).\n"
"context_rule_visibility(X, Y) :- cfa_parent(X, scope(Y)), scope(X), scope(Y).\n";
list<string>repHead_ = xreate::analysis::compile(head);
assert(repHead_.size() == 1);
list<string>repGuards_ = xreate::analysis::compile(guards);
assert(repGuards_.size() == 1);
list<string>repBody_ = xreate::analysis::compile(body);
assert(repBody_.size() == 1);
- const std::string& atomBindingScope = Config::get("clasp.bindings.scope");
+ const std::string& atomBindingScope = Config::get("transcend.bindings.scope");
boost::format formatContextVisibility("context_rule_visibility(ScopeX, %1%)");
boost::format formatScopeBind(atomBindingScope + "(ScopeX, %1%, Linkage)");
const string& repHead = str(formatScopeBind % repHead_.front());
const string& repGuards = str(formatScopeBind % repGuards_.front());
const string& repVisibility = str(formatContextVisibility % scopeId);
boost::format formatRule("%1%:- %2%, %3%, %4%.");
return prolog + str(formatRule % repHead % repGuards % repBody_.front() % repVisibility);
}
diff --git a/cpp/src/llvmlayer.cpp b/cpp/src/llvmlayer.cpp
index 5b97593..288d559 100644
--- a/cpp/src/llvmlayer.cpp
+++ b/cpp/src/llvmlayer.cpp
@@ -1,290 +1,241 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* llvmlayer.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
*/
/**
* \file llvmlayer.h
* \brief Wrapper over LLVM
*/
#include "ast.h"
#include "llvmlayer.h"
#include "ExternLayer.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/MCJIT.h"
#include "llvm/Support/TargetSelect.h"
#include <iostream>
#include <cmath>
using namespace llvm;
using namespace xreate;
using namespace std;
LLVMLayer::LLVMLayer(AST* root)
- : ast(root), builder(getGlobalContext()) {
- module = new llvm::Module(root->getModuleName(), llvm::getGlobalContext());
+ : llvmContext(),
+ builder(llvmContext),
+ ast(root),
+ module(new llvm::Module(root->getModuleName(), llvmContext))
+{
layerExtern = new ExternLayer(this);
layerExtern->init(root);
}
void*
LLVMLayer::getFunctionPointer(llvm::Function* function){
- uint64_t entryAddr = jit->getFunctionAddress(function->getName().str());
- return (void*) entryAddr;
+ uint64_t entryAddr = jit->getFunctionAddress(function->getName().str());
+ return (void*) entryAddr;
}
void
LLVMLayer::initJit(){
- std::string ErrStr;
- LLVMInitializeNativeTarget();
- llvm::InitializeNativeTargetAsmPrinter();
-
- llvm::EngineBuilder builder((std::unique_ptr<llvm::Module>(module)));
- jit = builder
- .setEngineKind(llvm::EngineKind::JIT)
- .setErrorStr(&ErrStr)
- .setVerifyModules(true)
- .create();
+ std::string ErrStr;
+ LLVMInitializeNativeTarget();
+ llvm::InitializeNativeTargetAsmPrinter();
+
+ llvm::EngineBuilder builder(std::unique_ptr<llvm::Module>(module.release()));
+ jit.reset(builder
+ .setEngineKind(llvm::EngineKind::JIT)
+ .setErrorStr(&ErrStr)
+ .setVerifyModules(true)
+ .create()
+ );
}
void
LLVMLayer::print(){
llvm::PassManager<llvm::Module> PM;
PM.addPass(llvm::PrintModulePass(llvm::outs(), "banner"));
- PM.run(*module);
-}
-
-llvm::BasicBlock*
-LLVMLayer::initExceptionBlock(llvm::BasicBlock* blockException){
- initExceptionsSupport();
-
- PointerType* tyInt8P = PointerType::getInt8PtrTy(llvm::getGlobalContext());
- Value* nullInt8P = llvm::ConstantPointerNull::get(tyInt8P);
-
-
- builder.SetInsertPoint(blockException);
- llvm::Function* fAllocate = module->getFunction("__cxa_allocate_exception");
- llvm::Function* fThrow = module->getFunction("__cxa_throw");
-
- auto exception = builder.CreateCall(fAllocate, ConstantInt::get(IntegerType::getInt64Ty(getGlobalContext()), 4));
- vector<Value*> throwParams{exception, nullInt8P, nullInt8P};
- builder.CreateCall(fThrow, ArrayRef<Value*>(throwParams));
- builder.CreateUnreachable();
-
- return blockException;
+ llvm::AnalysisManager<llvm::Module> aman;
+ PM.run(*module.get(), aman);
}
void
LLVMLayer::moveToGarbage(void *o)
{
__garbage.push_back(o);
}
llvm::Type*
LLVMLayer::
toLLVMType(const ExpandedType& ty) const {
- std::map<int, llvm::StructType*> empty;
- return toLLVMType(ty, empty);
+ std::map<int, llvm::StructType*> empty;
+ return toLLVMType(ty, empty);
}
llvm::Type*
LLVMLayer::
-toLLVMType(const ExpandedType& ty, std::map<int, llvm::StructType*>& conjuctions) const
-{
+toLLVMType(const ExpandedType& ty, std::map<int, llvm::StructType*>& conjuctions) const{
TypeAnnotation t = ty;
switch (t.__operator)
{
case TypeOperator::LIST:
{
assert(t.__operands.size()==1);
TypeAnnotation elTy = t.__operands.at(0);
return llvm::ArrayType::get(toLLVMType(ExpandedType(move(elTy)), conjuctions), t.__size);
}
case TypeOperator::LIST_NAMED:
{
std::vector<llvm::Type*> pack_;
pack_.reserve(t.__operands.size());
std::transform(t.__operands.begin(), t.__operands.end(), std::inserter(pack_, pack_.end()),
[this, &conjuctions](const TypeAnnotation& t){
return toLLVMType(ExpandedType(TypeAnnotation(t)), conjuctions);
});
llvm::ArrayRef<llvm::Type*> pack(pack_);
//process recursive types:
if (conjuctions.count(t.conjuctionId)) {
auto result = conjuctions[t.conjuctionId];
result->setBody(pack, false);
return result;
}
- return llvm::StructType::get(llvm::getGlobalContext(), pack, false);
+ return llvm::StructType::get(llvmContext, pack, false);
};
case TypeOperator::LINK: {
- llvm::StructType* conjuction = llvm::StructType::create(llvm::getGlobalContext());
+ llvm::StructType* conjuction = llvm::StructType::create(llvmContext);
int id = t.conjuctionId;
conjuctions.emplace(id, conjuction);
return conjuction;
};
case TypeOperator::CALL:
{
assert(false);
};
case TypeOperator::CUSTOM:
{
//Look in extern types
clang::QualType qt = layerExtern->lookupType(t.__valueCustom);
return layerExtern->toLLVMType(qt);
};
case TypeOperator::VARIANT: {
/* Variant Type Layout:
* struct {
* id: i8, Holds stored variant id
* storage: type of biggest variant
* }
*/
uint64_t sizeStorage=0;
- llvm::Type* typStorageRaw = llvm::Type::getVoidTy(llvm::getGlobalContext());
+ llvm::Type* typStorageRaw = llvm::Type::getVoidTy(llvmContext);
for(const TypeAnnotation& subtype: t.__operands){
llvm::Type* subtypeRaw = toLLVMType(ExpandedType(subtype), conjuctions);
uint64_t sizeSubtype = module->getDataLayout().getTypeStoreSize(subtypeRaw);
if (sizeSubtype > sizeStorage){
sizeStorage = sizeSubtype;
typStorageRaw = subtypeRaw;
}
}
std::vector<llvm::Type*> layout;
- layout.push_back(llvm::Type::getInt8Ty(llvm::getGlobalContext())); //id
+ layout.push_back(llvm::Type::getInt8Ty(llvmContext)); //id
const bool flagHoldsData = sizeStorage > 0;
if (flagHoldsData) {
layout.push_back(typStorageRaw); //storage
}
- return llvm::StructType::get(llvm::getGlobalContext(), llvm::ArrayRef<llvm::Type*>(layout));
+ return llvm::StructType::get(llvmContext, llvm::ArrayRef<llvm::Type*>(layout));
}
case TypeOperator::NONE: {
switch (t.__value) {
case TypePrimitive::I32:
case TypePrimitive::Int:
case TypePrimitive::Num:
- return llvm::Type::getInt32Ty(llvm::getGlobalContext());
+ return llvm::Type::getInt32Ty(llvmContext);
case TypePrimitive::Bool:
- return llvm::Type::getInt1Ty(llvm::getGlobalContext());
+ return llvm::Type::getInt1Ty(llvmContext);
case TypePrimitive::I8:
- return llvm::Type::getInt8Ty(llvm::getGlobalContext());
+ return llvm::Type::getInt8Ty(llvmContext);
case TypePrimitive::I64:
- return llvm::Type::getInt64Ty(llvm::getGlobalContext());
+ return llvm::Type::getInt64Ty(llvmContext);
case TypePrimitive::Float:
- return llvm::Type::getDoubleTy(llvm::getGlobalContext());
+ return llvm::Type::getDoubleTy(llvmContext);
case TypePrimitive::String:
- return llvm::Type::getInt8PtrTy(llvm::getGlobalContext());
+ return llvm::Type::getInt8PtrTy(llvmContext);
default:
assert(false);
}
}
default:
assert(false);
}
assert(false);
return nullptr;
}
-void
-LLVMLayer::initExceptionsSupport(){
- Type* typInt8Ptr = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
-
- if (!module->getFunction("__cxa_throw")) {
- std::vector<Type*> fThrowSignature{typInt8Ptr, typInt8Ptr, typInt8Ptr};
-
- FunctionType* tyFThrow = FunctionType::get(
- /*Result=*/Type::getVoidTy(module->getContext()),
- /*Params=*/fThrowSignature,
- /*isVarArg=*/false);
-
- llvm::Function::Create(
- /*Type=*/tyFThrow,
- /*Linkage=*/GlobalValue::ExternalLinkage,
- /*Name=*/"__cxa_throw", module); // (external, no body)
- }
-
- if (!module->getFunction("__cxa_allocate_exception")) {
- std::vector<Type*>fAllocateSignature{IntegerType::get(module->getContext(), 64)};
-
- FunctionType* tyFAllocate = FunctionType::get(
- /*Result=*/typInt8Ptr,
- /*Params=*/fAllocateSignature,
- /*isVarArg=*/false);
-
- llvm::Function::Create(
- /*Type=*/tyFAllocate,
- /*Linkage=*/GlobalValue::ExternalLinkage,
- /*Name=*/"__cxa_allocate_exception", module); // (external, no body)
- }
-}
-
bool TypeUtils::isStruct(const ExpandedType& ty){
const TypeAnnotation& t = ty.get();
if (t.__operator==TypeOperator::LIST_NAMED) {
return true;
}
if (t.__operator != TypeOperator::CUSTOM) {
return false;
}
clang::QualType tqual = llvm->layerExtern->lookupType(t.__valueCustom);
const clang::Type * raw = tqual.getTypePtr();
// TODO skip ALL the pointers until non-pointer type found
if (raw->isStructureType()) return true;
if (!raw->isAnyPointerType()) return false;
clang::QualType pointee = raw->getPointeeType();
return pointee->isStructureType();
}
bool TypeUtils::isPointer(const ExpandedType &ty) {
if (ty.get().__operator != TypeOperator::CUSTOM) return false;
clang::QualType qt = llvm->layerExtern->lookupType(ty.get().__valueCustom);
return llvm->layerExtern->isPointer(qt);
}
std::vector<std::string>
TypeUtils::getStructFields(const ExpandedType &t) {
return (t.get().__operator == TypeOperator::LIST_NAMED)
? t.get().fields
: llvm->layerExtern->getStructFields(
llvm->layerExtern->lookupType(t.get().__valueCustom));
}
diff --git a/cpp/src/llvmlayer.h b/cpp/src/llvmlayer.h
index 04a1093..900bb0d 100644
--- a/cpp/src/llvmlayer.h
+++ b/cpp/src/llvmlayer.h
@@ -1,67 +1,69 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* llvmlayer.h
*
* Author: pgess <v.melnychenko@xreate.org>
*/
#ifndef LLVMLAYER_H
#define LLVMLAYER_H
#include "llvm/IR/Module.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "utils.h"
namespace xreate {
- class AST;
- class ExternLayer;
- class TypeAnnotation;
- class LLVMLayer {
- public:
- LLVMLayer(AST* rootAST);
+class AST;
+class ExternLayer;
+class TypeAnnotation;
- AST *ast = 0;
- ExternLayer *layerExtern =0;
- llvm::Module *module = 0;
- llvm::ExecutionEngine* jit= 0;
- llvm::IRBuilder<> builder;
+class LLVMLayer {
+public:
+ LLVMLayer(AST* rootAST);
- void moveToGarbage(void *o);
+ mutable llvm::LLVMContext llvmContext;
+ llvm::IRBuilder<> builder;
+ AST *ast = 0;
+ ExternLayer *layerExtern =0;
+ std::unique_ptr<llvm::Module> module;
+ std::unique_ptr<llvm::ExecutionEngine> jit;
- llvm::Type* toLLVMType(const Expanded<TypeAnnotation>& ty) const;
- void print();
- void* getFunctionPointer(llvm::Function* function);
- void initJit();
+ void moveToGarbage(void *o);
- llvm::BasicBlock* initExceptionBlock(llvm::BasicBlock* block);
- private:
- void initExceptionsSupport();
- llvm::Type* toLLVMType(const Expanded<TypeAnnotation>& ty, std::map<int, llvm::StructType*>& conjunctions) const;
- std::vector<void *> __garbage;
- };
+ llvm::Type* toLLVMType(const Expanded<TypeAnnotation>& ty) const;
+ void print();
+ void* getFunctionPointer(llvm::Function* function);
+
+ void initJit();
+
+private:
+ llvm::Type* toLLVMType(const Expanded<TypeAnnotation>& ty, std::map<int, llvm::StructType*>& conjunctions) const;
+ std::vector<void *> __garbage;
+};
- struct TypeUtils {
- bool isStruct(const Expanded<TypeAnnotation>& ty);
- bool isPointer(const Expanded<TypeAnnotation>& ty);
- std::vector<std::string> getStructFields(const Expanded<TypeAnnotation>& t);
+struct TypeUtils {
+ bool isStruct(const Expanded<TypeAnnotation>& ty);
+ bool isPointer(const Expanded<TypeAnnotation>& ty);
+ std::vector<std::string> getStructFields(const Expanded<TypeAnnotation>& t);
- TypeUtils(LLVMLayer*llvmlayer)
- : llvm(llvmlayer){}
+ TypeUtils(LLVMLayer*llvmlayer)
+ : llvm(llvmlayer){}
- private:
- LLVMLayer* llvm;
- };
+ private:
+ LLVMLayer* llvm;
+};
+
}
#endif // LLVMLAYER_H
diff --git a/cpp/src/modules.cpp b/cpp/src/modules.cpp
index f610c9c..c8ff3f6 100644
--- a/cpp/src/modules.cpp
+++ b/cpp/src/modules.cpp
@@ -1,183 +1,183 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* modules.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on July 22, 2017, 5:13 PM
*/
/**
* \file modules.h
* \brief Modules support
*/
#include "modules.h"
#include "modules/Parser.h"
#include "analysis/utils.h"
#include <clingo/clingocontrol.hh>
#include <boost/format.hpp>
#include <regex>
#include <boost/filesystem.hpp>
#include <fstream>
namespace fs = boost::filesystem;
namespace xreate { namespace modules{
void
ModuleRecord::addModuleQuery(const Expression& query){
__queries.push_back(query);
}
void
ModuleRecord::addControllerPath(const std::string& path){
__controllers.push_back(path);
}
void
ModuleRecord::addDiscoveryPath(const std::string& path){
__discoveries.push_back(path);
}
void
ModuleRecord::addProperty(const Expression& prop){
__properties.push_back(prop);
}
void
ModulesSolver::loadControllers(const ModuleRecord& module){
for (const std::string& pathController: module.__controllers){
std::fstream fileContent(pathController);
__program << fileContent.rdbuf();
}
}
void
ModulesSolver::extractProperties(const ModuleRecord& module){
unsigned int moduleId = __registry->getModuleHash(module.__path);
const std::string atomProperty = "bind_module";
boost::format formatProperty(atomProperty + "(%1%, %2%).");
for (const Expression& property: module.__properties){
std::list<std::string> reprProp = xreate::analysis::compile(property);
assert(reprProp.size()== 1);
__program << (formatProperty % moduleId % reprProp.front())
<< std::endl;
}
}
void
ModulesSolver::discoverModules(const ModuleRecord& moduleClient){
std::regex extXreate("\\.xreate$", std::regex::basic);
for(const std::string& path: moduleClient.__discoveries){
for(fs::directory_entry e: fs::recursive_directory_iterator(path)) {
if (fs::is_regular_file(e.status())){
if (!std::regex_search(e.path().string(), extXreate)) continue;
FILE* script = fopen(e.path().c_str(), "r");
Scanner scanner(script);
Parser parser(&scanner);
parser.Parse();
assert(!parser.errors->count && "Discovery errors");
parser.module.__path = e.path().c_str();
extractProperties(parser.module);
fclose(script);
}
}
}
}
void
ModulesSolver::extractRequirements(const ModuleRecord& module){
const std::string atomQuery = "module_require";
boost::format formatProperty(atomQuery + "(%1%, %2%).");
unsigned int moduleId = __registry->getModuleHash(module.__path);
for (const Expression& query: module.__queries){
std::list<std::string> reprQuery = xreate::analysis::compile(query);
assert(reprQuery.size()== 1);
__program << (formatProperty % moduleId % reprQuery.front())
<< std::endl;
}
}
void
ModulesSolver::add(const std::string& base){
__program << base;
}
void
ModulesSolver::init(const std::string& programBase, const ModuleRecord& module){
add(programBase);
extractRequirements(module);
extractProperties(module);
loadControllers(module);
discoverModules(module);
std::cout << __program.str() << std::endl;
}
std::list<std::string>
ModulesSolver::run(const ModuleRecord& module){
const std::string atomDecision = "module_include";
unsigned int moduleId = __registry->getModuleHash(module.__path);
std::list<std::string> result;
std::vector<char const *> args{"clingo", nullptr};
DefaultGringoModule moduleDefault;
Gringo::Scripts scriptsDefault(moduleDefault);
ClingoLib ctl(scriptsDefault, 0, args.data(), {}, 0);
ctl.add("base", {}, __program.str());
ctl.ground({{"base", {}}}, nullptr);
ctl.solve([&atomDecision, this, &result, moduleId](Gringo::Model const &model) {
for (Gringo::Symbol atom : model.atoms(clingo_show_type_atoms)) {
std::cout << atom << std::endl;
if (std::strcmp(atom.name().c_str(), atomDecision.c_str())==0){
- auto rowDecision = ClaspLayer::parse<unsigned int, Gringo::Symbol>(atom);
+ auto rowDecision = TranscendLayer::parse<unsigned int, Gringo::Symbol>(atom);
unsigned int moduleIdActual = std::get<0>(rowDecision);
if (moduleIdActual == moduleId){
Gringo::Symbol moduleDecided = std::get<1>(rowDecision);
switch (moduleDecided.type()) {
case Gringo::SymbolType::Str:
result.push_back(moduleDecided.string().c_str());
break;
case Gringo::SymbolType::Num:
result.push_back(__registry->getModuleNameByHash(moduleDecided.num()));
break;
default: assert(false && "Inappropriate symbol type");
}
}
}
}
return true;
}, {});
return result;
}
const std::string&
ModulesRegistry::getModuleNameByHash(unsigned int hash){
auto result = __registry.right.find(hash);
assert(result != __registry.right.end());
return result->second;
}
unsigned int
ModulesRegistry::getModuleHash(const std::string& moduleName){
auto result = __registry.left.insert(Hash::left_value_type(moduleName, __registry.size()));
return result.first->second;
}
}} //namespace xreate::modules
diff --git a/cpp/src/pass/abstractpass.cpp b/cpp/src/pass/abstractpass.cpp
index 17f8385..9cc6285 100644
--- a/cpp/src/pass/abstractpass.cpp
+++ b/cpp/src/pass/abstractpass.cpp
@@ -1,103 +1,103 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
*/
/**
* \file abstractpass.h
* \brief Infrastructure to iterate over AST to facilitate analysis and compilation.
*/
#include "abstractpass.h"
#include "attachments.h"
#include "xreatemanager.h"
using namespace std;
namespace xreate {
template<>
void defaultValue<void>(){}
void IPass::finish(){}
IPass::IPass(PassManager *manager)
: man(manager) {
}
template<>
void
AbstractPass<void>::processSymbol(const Symbol& symbol, PassContext context, const std::string& hintSymbol)
{
if (__visitedSymbols.isCached(symbol))
return;
__visitedSymbols.setCachedValue(symbol);
const Expression& declaration = CodeScope::getDefinition(symbol, true);
if (declaration.isDefined()){
PassContext context2 = context.updateScope(symbol.scope);
process(declaration, context2, hintSymbol);
}
}
template<>
void
AbstractPass<void>::process(const Expression& expression, PassContext context, const std::string& varDecl){
if (expression.__state == Expression::COMPOUND){
for (const Expression &op: expression.getOperands()) {
process(op, context);
}
for (CodeScope* scope: expression.blocks) {
process(scope, context);
}
if (expression.op == Operator::CALL){
processExpressionCall(expression, context);
}
return;
}
if (expression.__state == Expression::IDENT){
assert(context.scope);
processSymbol(Attachments::get<IdentifierSymbol>(expression), context, expression.getValueString());
}
}
}
/**
* \class xreate::IPass
*
* Each pass has to have IPass interface to be controllable by XreateManager.
* However in most cases users should inherit minimal useful implementation xreate::AbstractPass
*
* \note It's usually expected that custom Pass publish processing results by one of the following means:
* - xreate::Attachments for communicating with other Passes
- * - IAnalysisReport to feed xreate::ClaspLayer solver
+ * - IAnalysisReport to feed xreate::TranscendLayer solver
*
* \sa xreate::XreateManager, xreate::AbstractPass
*/
/**
* \class xreate::AbstractPass
*
* Iterates over %AST and provides functions to alter processing of particular %AST nodes.
* Thus client should not re-implement every possible node processing
* and it's enough to focus only on relevant nodes.
*
* Template parameter `Output` specify type of node processing result data.
*
* Automatically caches already visited nodes
*
* \note It's usually expected that custom Pass publish processing results by one of the following means:
* - xreate::Attachments for communicating with other Passes
- * - IAnalysisReport to feed xreate::ClaspLayer solver
+ * - IAnalysisReport to feed xreate::TranscendLayer solver
*
*
* \sa xreate::XreateManager, xreate::IPass, xreate::AST
*/
diff --git a/cpp/src/pass/cfapass.cpp b/cpp/src/pass/cfapass.cpp
index e4fdcb4..de391a6 100644
--- a/cpp/src/pass/cfapass.cpp
+++ b/cpp/src/pass/cfapass.cpp
@@ -1,196 +1,196 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* cfapass.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
*/
/**
* \file cfapass.h
* \brief Control Flow Analysis(CFA)
*/
#include "cfapass.h"
#include "analysis/cfagraph.h"
#include "analysis/DominatorsTreeAnalysisProvider.h"
#include <boost/range/iterator_range_core.hpp>
using namespace std;
using namespace xreate::cfa;
void
CFAPassBasic::initSignatures(){
auto range = man->root->__interfacesData.equal_range(CFA);
for (auto i = range.first; i!= range.second; ++i){
__signatures.emplace(i->second.op, i->second);
}
}
void
CFAPassBasic::run(){
initSignatures();
return AbstractPass::run();
}
void
CFAPassBasic::finish(){
- man->clasp->registerReport(__context.graph);
+ man->transcend->registerReport(__context.graph);
dominators::DominatorsTreeAnalysisProvider* reportDominators = new dominators::DominatorsTreeAnalysisProvider();
reportDominators->run(__context.graph);
- man->clasp->registerReport(reportDominators);
+ man->transcend->registerReport(reportDominators);
return AbstractPass::finish();
}
void
CFAPassBasic::processFnCall(ManagedFnPtr function, PassContext context){
- ClaspLayer* clasp = man->clasp;
- __context.graph->addCallConnection(clasp->pack(context.scope), function->getName());
+ TranscendLayer* transcend = man->transcend;
+ __context.graph->addCallConnection(transcend->pack(context.scope), function->getName());
return AbstractPass::processFnCall(function, context);
}
void
CFAPassBasic::processFnCallUncertain(ManagedFnPtr function, PassContext context){
- ClaspLayer* clasp = man->clasp;
- __context.graph->addCallConnection(clasp->pack(context.scope), function->getName());
+ TranscendLayer* transcend = man->transcend;
+ __context.graph->addCallConnection(transcend->pack(context.scope), function->getName());
return AbstractPass::processFnCallUncertain(function, context);
}
void
CFAPassBasic::process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl){
- ClaspLayer* clasp = man->clasp;
+ TranscendLayer* transcend = man->transcend;
const CodeScope* scopeParent = context.scope;
- ScopePacked scopeId = clasp->pack(scope);
+ ScopePacked scopeId = transcend->pack(scope);
//Parent Relations
if (scopeParent){
- __context.graph->addParentConnection(scopeId, clasp->pack(scopeParent));
+ __context.graph->addParentConnection(scopeId, transcend->pack(scopeParent));
} else {
__context.graph->addParentConnection(scopeId, context.function->getName());
}
//TOTEST scope annotations
//SECTIONTAG context gather scope annotations
__context.graph->addScopeAnnotations(scopeId, scope->tags);
__context.graph->addContextRules(scopeId, scope->contextRules);
return AbstractPass::process(scope, context, hintBlockDecl);
}
//TOTEST scope annotations via scheme
void
CFAPassBasic::process(const Expression& expression, PassContext context, const std::string& varDecl){
- ClaspLayer* clasp = man->clasp;
+ TranscendLayer* transcend = man->transcend;
if (expression.__state == Expression::COMPOUND){
Operator op= expression.op;
if (__signatures.count(op)) {
assert(expression.blocks.size());
for (const auto& scheme: boost::make_iterator_range(__signatures.equal_range(expression.op))) {
- __context.graph->addScopeAnnotations(clasp->pack(expression.blocks.front()), scheme.second.getOperands());
+ __context.graph->addScopeAnnotations(transcend->pack(expression.blocks.front()), scheme.second.getOperands());
}
}
}
return AbstractPass::process(expression, context, varDecl);
}
void
CFAPassBasic::process(ManagedFnPtr function){
__context.graph->addFunctionAnnotations(function->getName(), function->getTags());
return AbstractPass::process(function);
}
CFAPassBasic::CFAPassBasic(PassManager* manager)
: AbstractPass(manager)
- , __context{new CFAGraph(manager->clasp)}
+ , __context{new CFAGraph(manager->transcend)}
{}
/****************************SCOPE DEPENDENCIES********************************/
void
CFAPassDependenciesDecorator::process(const Expression& expression, PassContext context, const std::string& varDecl){
- ClaspLayer* clasp = man->clasp;
+ TranscendLayer* transcend = man->transcend;
if (expression.__state == Expression::COMPOUND)
switch(expression.op){
case Operator::SEQUENCE:{
- ScopePacked scopePrev = clasp->pack(expression.blocks.front());
+ ScopePacked scopePrev = transcend->pack(expression.blocks.front());
for(auto scopeIt= ++expression.blocks.begin(); scopeIt != expression.blocks.end(); ++scopeIt){
- ScopePacked scopeCurrent = clasp->pack(*scopeIt);
+ ScopePacked scopeCurrent = transcend->pack(*scopeIt);
__context.graph->addDependency(scopeCurrent, scopePrev);
scopePrev = scopeCurrent;
}
break;
}
default: break;
}
return Parent::process(expression, context, varDecl);
}
void
CFAPassDependenciesDecorator::processFnCall(ManagedFnPtr function, PassContext context){
- ClaspLayer* clasp = man->clasp;
+ TranscendLayer* transcend = man->transcend;
const CodeScope* scopeCaller = context.scope;
assert(scopeCaller);
- ScopePacked scopeCallerPacked = clasp->pack(scopeCaller);
+ ScopePacked scopeCallerPacked = transcend->pack(scopeCaller);
if(__context.graph->isDependent(scopeCallerPacked)){
- ScopePacked scopeCalleePacked = clasp->pack(function->getEntryScope());
+ ScopePacked scopeCalleePacked = transcend->pack(function->getEntryScope());
__context.graph->transmitDependencies(scopeCalleePacked, scopeCallerPacked);
}
Parent::processFnCall(function, context);
}
void
CFAPassDependenciesDecorator::processFnCallUncertain(ManagedFnPtr function, PassContext context){
- ClaspLayer* clasp = man->clasp;
+ TranscendLayer* transcend = man->transcend;
const CodeScope* scopeCaller = context.scope;
assert(scopeCaller);
- ScopePacked scopeCallerPacked = clasp->pack(scopeCaller);
+ ScopePacked scopeCallerPacked = transcend->pack(scopeCaller);
if(__context.graph->isDependent(scopeCallerPacked)){
- ScopePacked scopeCalleePacked = clasp->pack(function->getEntryScope());
+ ScopePacked scopeCalleePacked = transcend->pack(function->getEntryScope());
__context.graph->transmitDependencies(scopeCalleePacked, scopeCallerPacked);
}
Parent::processFnCallUncertain(function, context);
}
void
CFAPassDependenciesDecorator::process(CodeScope* scope,
PassContext context, const std::string& hintBlockDecl){
- ClaspLayer* clasp = man->clasp;
+ TranscendLayer* transcend = man->transcend;
const CodeScope* scopeParent = context.scope;
if (scopeParent){
- ScopePacked scopePacked = clasp->pack(scope);
- ScopePacked scopeParentPacked = clasp->pack(scopeParent);
+ ScopePacked scopePacked = transcend->pack(scope);
+ ScopePacked scopeParentPacked = transcend->pack(scopeParent);
if (!__context.graph->isDependent(scopePacked) &&
__context.graph->isDependent(scopeParentPacked)) {
__context.graph->transmitDependencies(scopePacked, scopeParentPacked);
}
}
Parent::process(scope, context, hintBlockDecl);
}
/**
* \class xreate::cfa::CFAPass
* \details Provides CFA, important analysis for reasoning. Iterates over AST and stores collected data in CFAGraph
- */
\ No newline at end of file
+ */
diff --git a/cpp/src/pass/cfapass.h b/cpp/src/pass/cfapass.h
index 6351126..20f7467 100644
--- a/cpp/src/pass/cfapass.h
+++ b/cpp/src/pass/cfapass.h
@@ -1,67 +1,67 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
*
* cfapass.cpp
* Control Flow Graph building pass
*/
#ifndef CFGPASS_H
#define CFGPASS_H
#include "xreatemanager.h"
-#include "clasplayer.h"
+#include "transcendlayer.h"
#include "abstractpass.h"
namespace xreate{namespace cfa {
class CFAGraph;
/** \brief Control Flow Analysis Pass(%CFA)*/
class CFAPassBasic : public AbstractPass<void>{
public:
void process(ManagedFnPtr function) override;
void processFnCall(ManagedFnPtr function, PassContext context) override;
void processFnCallUncertain(ManagedFnPtr function, PassContext context) override;
void process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl="") override;
void process(const Expression& expression, PassContext context, const std::string& varDecl="") override;
CFAPassBasic(PassManager* manager);
void finish() override;
void run() override;
const CFAGraph* getReport() const {return __context.graph; }
protected:
struct {
CFAGraph* graph;
} __context;
std::multimap<Operator, Expression> __signatures; //CFA data for particular operators
void initSignatures();
};
class CFAPassDependenciesDecorator: public CFAPassBasic{
typedef CFAPassBasic Parent;
public:
CFAPassDependenciesDecorator(PassManager* manager): CFAPassBasic(manager) {}
void process(const Expression& expression, PassContext context, const std::string& varDecl) override;
void processFnCall(ManagedFnPtr function, PassContext context) override;
void processFnCallUncertain(ManagedFnPtr function, PassContext context) override;
void process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl) override;
};
class CFAPass: public CFAPassDependenciesDecorator{
public:
CFAPass(PassManager* manager): CFAPassDependenciesDecorator(manager) {}
};
}} //end of namespace xreate::cfa
#endif // CFGPASS_H
diff --git a/cpp/src/pass/compilepass.cpp b/cpp/src/pass/compilepass.cpp
index af39d52..f39e74c 100644
--- a/cpp/src/pass/compilepass.cpp
+++ b/cpp/src/pass/compilepass.cpp
@@ -1,716 +1,716 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
*
* compilepass.cpp
*/
/**
* \file compilepass.h
* \brief Compilation pass
*/
#include "compilepass.h"
-#include "clasplayer.h"
+#include "transcendlayer.h"
#include <ast.h>
#include "llvmlayer.h"
#include "query/containers.h"
#include "compilation/containers.h"
#include "ExternLayer.h"
#include "compilation/targetinterpretation.h"
#include "pass/versionspass.h"
#include "compilation/scopedecorators.h"
#include "compilation/operators.h"
+#include "compilation/latereasoning.h"
#include "analysis/typeinference.h"
#include <boost/optional.hpp>
#include <memory>
#include <iostream>
using namespace std;
using namespace llvm;
namespace xreate { namespace compilation{
std::string
BasicFunctionUnit::prepareName(){
AST* ast = IFunctionUnit::pass->man->root;
string name = ast->getFunctionSpecializations(IFunctionUnit::function->__name).size() > 1 ?
IFunctionUnit::function->__name + std::to_string(IFunctionUnit::function.id()) :
IFunctionUnit::function->__name;
return name;
}
std::vector<llvm::Type*>
BasicFunctionUnit::prepareArguments() {
LLVMLayer* llvm = IFunctionUnit::pass->man->llvm;
AST* ast = IFunctionUnit::pass->man->root;
CodeScope* entry = IFunctionUnit::function->__entry;
std::vector<llvm::Type*> signature;
std::transform(entry->__bindings.begin(), entry->__bindings.end(), std::inserter(signature, signature.end()),
[llvm, ast, entry](const std::string & arg)->llvm::Type* {
assert(entry->__identifiers.count(arg));
ScopedSymbol argid{entry->__identifiers.at(arg), versions::VERSION_NONE};
return llvm->toLLVMType(ast->expandType(entry->__declarations.at(argid).type));
});
return signature;
}
llvm::Type*
BasicFunctionUnit::prepareResult() {
LLVMLayer* llvm = IFunctionUnit::pass->man->llvm;
AST* ast = IFunctionUnit::pass->man->root;
CodeScope* entry = IFunctionUnit::function->__entry;
return llvm->toLLVMType(ast->expandType(entry->__declarations.at(ScopedSymbol::RetSymbol).type));
}
llvm::Function::arg_iterator
BasicFunctionUnit::prepareBindings() {
CodeScope* entry = IFunctionUnit::function->__entry;
ICodeScopeUnit* entryCompilation = IFunctionUnit::getScopeUnit(entry);
llvm::Function::arg_iterator fargsI = IFunctionUnit::raw->arg_begin();
for (std::string &arg : entry->__bindings) {
ScopedSymbol argid{entry->__identifiers[arg], versions::VERSION_NONE};
entryCompilation->bindArg(&*fargsI, argid);
fargsI->setName(arg);
++fargsI;
}
return fargsI;
}
//DEBT compiler rigidly depends on exact definition of DefaultFunctionUnit
typedef BasicFunctionUnit DefaultFunctionUnit;
ICodeScopeUnit::ICodeScopeUnit(const CodeScope* const codeScope, IFunctionUnit* f, CompilePass* compilePass)
: pass(compilePass), function(f), scope(codeScope), currentBlockRaw(nullptr) {
}
llvm::Value*
CallStatementRaw::operator()(std::vector<llvm::Value *>&& args, const std::string& hintDecl) {
llvm::Function* calleeInfo = dyn_cast<llvm::Function>(__callee);
if (calleeInfo) {
auto argsFormal = calleeInfo->args();
int pos = 0;
//SECTIONTAG types/convert function ret value
for (auto argFormal = argsFormal.begin(); argFormal != argsFormal.end(); ++argFormal, ++pos) {
args[pos] = typeinference::doAutomaticTypeConversion(args[pos], argFormal->getType(), llvm->builder);
}
}
//Do not name function call that returns Void.
std::string nameStatement = hintDecl;
if (calleeInfo->getReturnType()->isVoidTy()){
nameStatement.clear();
}
return llvm->builder.CreateCall(__calleeTy, __callee, args, nameStatement);
}
//DESABLEDFEATURE implement inlining
class CallStatementInline : public ICallStatement {
public:
CallStatementInline(IFunctionUnit* caller, IFunctionUnit* callee, LLVMLayer* l)
: __caller(caller), __callee(callee), llvm(l) {
}
llvm::Value* operator()(std::vector<llvm::Value *>&& args, const std::string& hintDecl) {
//TOTEST inlining
// CodeScopeUnit* entryCompilation = outer->getScopeUnit(function->__entry);
// for(int i=0, size = args.size(); i<size; ++i) {
// entryCompilation->bindArg(args.at(i), string(entryCompilation->scope->__bindings.at(i)));
// }
//
//
// return entryCompilation->compile();
return nullptr;
}
private:
IFunctionUnit* __caller;
IFunctionUnit* __callee;
LLVMLayer* llvm;
bool isInline() {
// Symbol ret = Symbol{0, function->__entry};
// bool flagOnTheFly = SymbolAttachments::get<IsImplementationOnTheFly>(ret, false);
//TODO consider inlining
return false;
}
};
BasicCodeScopeUnit::BasicCodeScopeUnit(const CodeScope* const codeScope, IFunctionUnit* f, CompilePass* compilePass)
: ICodeScopeUnit(codeScope, f, compilePass) {
}
llvm::Value*
BasicCodeScopeUnit::processSymbol(const Symbol& s, std::string hintRetVar) {
Expression declaration = CodeScope::getDefinition(s);
const CodeScope* scope = s.scope;
ICodeScopeUnit* scopeExternal = ICodeScopeUnit::function->getScopeUnit(scope);
llvm::Value* resultRaw;
if (scopeExternal == this){
resultRaw = process(declaration, hintRetVar);
currentBlockRaw = pass->man->llvm->builder.GetInsertBlock();
} else {
assert(scopeExternal->currentBlockRaw);
llvm::BasicBlock* blockOwn = pass->man->llvm->builder.GetInsertBlock();
pass->man->llvm->builder.SetInsertPoint(scopeExternal->currentBlockRaw);
resultRaw = scopeExternal->processSymbol(s, hintRetVar);
pass->man->llvm->builder.SetInsertPoint(blockOwn);
}
return resultRaw;
}
ICallStatement*
BasicCodeScopeUnit::findFunction(const Expression& opCall) {
const std::string& calleeName = opCall.getValueString();
LLVMLayer* llvm = pass->man->llvm;
const std::list<ManagedFnPtr>& specializations = pass->man->root->getFunctionSpecializations(calleeName);
//if no specializations registered - check external function
if (specializations.size() == 0) {
llvm::Function* external = llvm->layerExtern->lookupFunction(calleeName);
llvm::outs() << "Debug/External function: " << calleeName;
external->getType()->print(llvm::outs(), true);
llvm::outs() << "\n";
return new CallStatementRaw(external, llvm);
}
//There should be only one specialization without any valid guards at this point
return new CallStatementRaw(pass->getFunctionUnit(
pass->man->root->findFunction(calleeName))->compile(),
llvm);
}
//DISABLEDFEATURE transformations
// if (pass->transformations->isAcceptable(expr)){
// return pass->transformations->transform(expr, result, ctx);
// }
llvm::Value*
BasicCodeScopeUnit::process(const Expression& expr, const std::string& hintVarDecl) {
#define DEFAULT(x) (hintVarDecl.empty()? x: hintVarDecl)
llvm::Value *left;
llvm::Value *right;
LLVMLayer& l = *pass->man->llvm;
xreate::compilation::AdvancedInstructions instructions = xreate::compilation::AdvancedInstructions({this, function, pass});
switch (expr.op) {
case Operator::SUB: case Operator::MUL:
case Operator::DIV: case Operator::EQU: case Operator::LSS:
case Operator::GTR: case Operator::NE: case Operator::LSE:
case Operator::GTE:
assert(expr.__state == Expression::COMPOUND);
assert(expr.operands.size() == 2);
left = process(expr.operands[0]);
right = process(expr.operands[1]);
//SECTIONTAG types/convert binary operation
right = typeinference::doAutomaticTypeConversion(right, left->getType(), l.builder);
break;
default:;
}
switch (expr.op) {
case Operator::ADD:
{
left = process(expr.operands[0]);
Context context{this, function, pass};
llvm::Value* resultSU = StructUpdate::add(expr.operands[0], left, expr.operands[1], context, DEFAULT("tmp_add"));
if (resultSU) return resultSU;
right = process(expr.operands[1]);
llvm::Value* resultAddPA = pointerarithmetic::PointerArithmetic::add(left, right, context, DEFAULT("tmp_add"));
if (resultAddPA) {
return resultAddPA;
}
return l.builder.CreateAdd(left, right, DEFAULT("tmp_add"));
break;
}
case Operator::SUB:
return l.builder.CreateSub(left, right, DEFAULT("tmp_sub"));
break;
case Operator::MUL:
return l.builder.CreateMul(left, right, DEFAULT("tmp_mul"));
break;
case Operator::DIV:
return l.builder.CreateSDiv(left, right, DEFAULT("tmp_div"));
break;
case Operator::EQU:
if (left->getType()->isIntegerTy()) return l.builder.CreateICmpEQ(left, right, DEFAULT("tmp_equ"));
if (left->getType()->isFloatingPointTy()) return l.builder.CreateFCmpOEQ(left, right, DEFAULT("tmp_equ"));
break;
case Operator::NE:
return l.builder.CreateICmpNE(left, right, DEFAULT("tmp_ne"));
break;
case Operator::LSS:
return l.builder.CreateICmpSLT(left, right, DEFAULT("tmp_lss"));
break;
case Operator::LSE:
return l.builder.CreateICmpSLE(left, right, DEFAULT("tmp_lse"));
break;
case Operator::GTR:
return l.builder.CreateICmpSGT(left, right, DEFAULT("tmp_gtr"));
break;
case Operator::GTE:
return l.builder.CreateICmpSGE(left, right, DEFAULT("tmp_gte"));
break;
case Operator::NEG:
left = process(expr.operands[0]);
return l.builder.CreateNeg(left, DEFAULT("tmp_neg"));
break;
case Operator::CALL:
{
assert(expr.__state == Expression::COMPOUND);
shared_ptr<ICallStatement> callee(findFunction(expr));
const std::string& nameCallee = expr.getValueString();
//prepare arguments
std::vector<llvm::Value *> args;
args.reserve(expr.operands.size());
std::transform(expr.operands.begin(), expr.operands.end(), std::inserter(args, args.end()),
[this](const Expression & operand) {
return process(operand);
}
);
return (*callee)(move(args), DEFAULT("res_" + nameCallee));
}
case Operator::IF:
{
return instructions.compileIf(expr, DEFAULT("tmp_if"));
}
case Operator::SWITCH:
{
return instructions.compileSwitch(expr, DEFAULT("tmp_switch"));
}
- case Operator::LOOP_CONTEXT:
- {
- assert(false);
- return nullptr;
- //return instructions.compileLoopContext(expr, DEFAULT("tmp_loop"));
- }
-
case Operator::LOGIC_AND:
{
assert(expr.operands.size() == 1);
return process(expr.operands[0]);
}
case Operator::LIST:
{
return instructions.compileListAsSolidArray(expr, DEFAULT("tmp_list"));
};
case Operator::LIST_RANGE:
{
assert(false); //no compilation phase for a range list
// return InstructionList(this).compileConstantArray(expr, l, hintRetVar);
};
case Operator::LIST_NAMED:
{
typedef Expanded<TypeAnnotation> ExpandedType;
ExpandedType tyStructLiteral = l.ast->getType(expr);
const std::vector<string> fieldsFormal = (tyStructLiteral.get().__operator == TypeOperator::CUSTOM) ?
l.layerExtern->getStructFields(l.layerExtern->lookupType(tyStructLiteral.get().__valueCustom))
: tyStructLiteral.get().fields;
std::map<std::string, size_t> indexFields;
for (size_t i = 0, size = fieldsFormal.size(); i < size; ++i) {
indexFields.emplace(fieldsFormal[i], i);
}
llvm::StructType* tyLiteralRaw = llvm::cast<llvm::StructType>(l.toLLVMType(tyStructLiteral));
llvm::Value* record = llvm::UndefValue::get(tyLiteralRaw);
for (size_t i = 0; i < expr.operands.size(); ++i) {
const Expression& operand = expr.operands.at(i);
unsigned int fieldId = indexFields.at(expr.bindings.at(i));
llvm::Value* result = process(operand);
assert(result);
record = l.builder.CreateInsertValue(record, result, llvm::ArrayRef<unsigned>({fieldId}));
}
return record;
};
case Operator::MAP:
{
assert(expr.blocks.size());
return instructions.compileMapSolidOutput(expr, DEFAULT("map"));
};
case Operator::FOLD:
{
return instructions.compileFold(expr, DEFAULT("fold"));
};
case Operator::FOLD_INF:
{
return instructions.compileFoldInf(expr, DEFAULT("fold"));
};
case Operator::INDEX:
{
//TASK allow multiindex compilation
assert(expr.operands.size() == 2);
assert(expr.operands[0].__state == Expression::IDENT);
const std::string& hintIdent = expr.operands[0].getValueString();
Symbol s = Attachments::get<IdentifierSymbol>(expr.operands[0]);
const ExpandedType& t2 = pass->man->root->getType(expr.operands[0]);
llvm::Value* aggr = processSymbol(s, hintIdent);
switch (t2.get().__operator) {
case TypeOperator::LIST_NAMED: case TypeOperator::CUSTOM:
{
std::string idxField;
const Expression& idx = expr.operands.at(1);
switch (idx.__state) {
//named struct field
case Expression::STRING:
idxField = idx.getValueString();
break;
//anonymous struct field
case Expression::NUMBER:
idxField = to_string((int) idx.getValueDouble());
break;
default:
assert(false && "Wrong index for a struct");
}
return instructions.compileStructIndex(aggr, t2, idxField);
};
case TypeOperator::LIST:
{
std::vector<llvm::Value*> indexes;
std::transform(++expr.operands.begin(), expr.operands.end(), std::inserter(indexes, indexes.end()),
[this] (const Expression & op) {
return process(op);
}
);
return instructions.compileArrayIndex(aggr, indexes, DEFAULT(string("el_") + hintIdent));
};
default:
assert(false);
}
};
case Operator::CALL_INTRINSIC:
{
const std::string op = expr.getValueString();
if (op == "copy") {
llvm::Value* result = process(expr.getOperands().at(0));
auto decoratorVersions = Decorators<VersionsScopeDecoratorTag>::getInterface(this);
llvm::Value* storage = decoratorVersions->processIntrinsicInit(result->getType());
decoratorVersions->processIntrinsicCopy(result, storage);
return l.builder.CreateLoad(storage, hintVarDecl);
}
assert(false && "undefined intrinsic");
}
case Operator::VARIANT:
{
const ExpandedType& typVariant = pass->man->root->getType(expr);
llvm::Type* typVariantRaw = l.toLLVMType(typVariant);
llvm::Type* typIdRaw = llvm::cast<llvm::StructType>(typVariantRaw)->getElementType(0);
uint64_t id = expr.getValueDouble();
llvm::Value* variantRaw = llvm::UndefValue::get(typVariantRaw);
variantRaw = l.builder.CreateInsertValue(variantRaw, llvm::ConstantInt::get(typIdRaw, id), llvm::ArrayRef<unsigned>({0}));
const bool flagDoReference = expr.operands.size();
if (flagDoReference){
const ExpandedType& subtyp = ExpandedType(typVariant->__operands.at(id));
llvm::Type* subtypRaw = l.toLLVMType(subtyp);
Attachments::put<TypeInferred>(expr.operands.at(0), subtyp);
llvm::Value* subtypValue = process(expr.operands.at(0));
llvm::Type* typStorageRaw = llvm::cast<llvm::StructType>(typVariantRaw)->getElementType(1);
llvm::Value* addrAsStorage = l.builder.CreateAlloca(typStorageRaw);
llvm::Value* addrAsSubtyp = l.builder.CreateBitOrPointerCast(addrAsStorage, subtypRaw->getPointerTo());
l.builder.CreateStore(subtypValue, addrAsSubtyp);
llvm::Value* storageRaw = l.builder.CreateLoad(typStorageRaw, addrAsStorage);
variantRaw = l.builder.CreateInsertValue(variantRaw, storageRaw, llvm::ArrayRef<unsigned>({1}));
}
return variantRaw;
}
- case Operator::SWITCH_VARIANT:
- {
+ case Operator::SWITCH_VARIANT: {
return instructions.compileSwitchVariant(expr, DEFAULT("tmpswitch"));
}
+ case Operator::SWITCH_LATE: {
+ latereasoning::LateReasoningCompiler compiler({this, function, pass});
+ return compiler.compile(expr, DEFAULT("switchlate"));
+ }
+
case Operator::SEQUENCE: {
return instructions.compileSequence(expr);
}
case Operator::UNDEF: {
llvm::Type* typExprUndef = l.toLLVMType(typeinference::getType(expr, *pass->man->root));
return llvm::UndefValue::get(typExprUndef);
}
case Operator::INVALID:
assert(expr.__state != Expression::COMPOUND);
switch (expr.__state) {
case Expression::IDENT:
{
Symbol s = Attachments::get<IdentifierSymbol>(expr);
return processSymbol(s, expr.getValueString());
}
case Expression::NUMBER:
{
llvm::Type* typConst = l.toLLVMType(typeinference::getType(expr, *pass->man->root));
int literal = expr.getValueDouble();
return llvm::ConstantInt::get(typConst, literal);
}
case Expression::STRING:
{
return instructions.compileConstantStringAsPChar(expr.getValueString(), DEFAULT("tmp_str"));
};
default:
{
break;
}
};
break;
default: break;
}
assert(false && "Can't compile expression");
return 0;
}
llvm::Value*
BasicCodeScopeUnit::compile(const std::string& hintBlockDecl) {
+ LLVMLayer* llvm = pass->man->llvm;
+
if (!hintBlockDecl.empty()) {
- llvm::BasicBlock *block = llvm::BasicBlock::Create(llvm::getGlobalContext(), hintBlockDecl, function->raw);
+ llvm::BasicBlock *block = llvm::BasicBlock::Create(llvm->llvmContext, hintBlockDecl, function->raw);
pass->man->llvm->builder.SetInsertPoint(block);
}
currentBlockRaw = pass->man->llvm->builder.GetInsertBlock();
Symbol symbScope = Symbol{ScopedSymbol::RetSymbol, scope};
return processSymbol(symbScope);
}
ICodeScopeUnit::~ICodeScopeUnit() {
}
IFunctionUnit::~IFunctionUnit() {
}
llvm::Function*
IFunctionUnit::compile() {
if (raw != nullptr) return raw;
LLVMLayer* llvm = pass->man->llvm;
llvm::IRBuilder<>& builder = llvm->builder;
string&& functionName = prepareName();
std::vector<llvm::Type*>&& types = prepareArguments();
llvm::Type* expectedResultType = prepareResult();
llvm::FunctionType *ft = llvm::FunctionType::get(expectedResultType, types, false);
raw = llvm::cast<llvm::Function>(llvm->module->getOrInsertFunction(functionName, ft));
prepareBindings();
const std::string&blockName = "entry";
llvm::BasicBlock* blockCurrent = builder.GetInsertBlock();
llvm::Value* result = getScopeUnit(function->__entry)->compile(blockName);
assert(result);
//SECTIONTAG types/convert function ret value
builder.CreateRet(typeinference::doAutomaticTypeConversion(result, expectedResultType, llvm->builder));
if (blockCurrent) {
builder.SetInsertPoint(blockCurrent);
}
llvm->moveToGarbage(ft);
return raw;
}
ICodeScopeUnit*
IFunctionUnit::getScopeUnit(const CodeScope * const scope) {
if (__scopes.count(scope)) {
auto result = __scopes.at(scope).lock();
if (result) {
return result.get();
}
}
std::shared_ptr<ICodeScopeUnit> unit(pass->buildCodeScopeUnit(scope, this));
if (scope->__parent != nullptr) {
auto parentUnit = Decorators<CachedScopeDecoratorTag>::getInterface(getScopeUnit(scope->__parent));
parentUnit->registerChildScope(unit);
} else {
__orphanedScopes.push_back(unit);
}
if (!__scopes.emplace(scope, unit).second) {
__scopes[scope] = unit;
}
return unit.get();
}
ICodeScopeUnit*
IFunctionUnit::getScopeUnit(ManagedScpPtr scope) {
return getScopeUnit(&*scope);
}
ICodeScopeUnit*
IFunctionUnit::getEntry() {
return getScopeUnit(function->getEntryScope());
}
template<>
compilation::IFunctionUnit*
CompilePassCustomDecorators<void, void>::buildFunctionUnit(const ManagedFnPtr& function){
return new DefaultFunctionUnit(function, this);
}
template<>
compilation::ICodeScopeUnit*
CompilePassCustomDecorators<void, void>::buildCodeScopeUnit(const CodeScope* const scope, IFunctionUnit* function){
return new DefaultCodeScopeUnit(scope, function, this);
}
} // end of compilation
compilation::IFunctionUnit*
CompilePass::getFunctionUnit(const ManagedFnPtr& function) {
unsigned int id = function.id();
if (!functions.count(id)) {
compilation::IFunctionUnit* unit = buildFunctionUnit(function);
functions.emplace(id, unit);
return unit;
}
return functions.at(id);
}
void
CompilePass::run() {
managerTransformations = new xreate::compilation::TransformationsManager();
targetInterpretation = new interpretation::TargetInterpretation(this->man->root, this);
//Find out main function;
- StaticModel model = man->clasp->query(Config::get("function-entry"));
+ StaticModel model = man->transcend->query(Config::get("function-entry"));
assert(model.size() && "Error: No entry function found");
assert(model.size() == 1 && "Error: Ambiguous entry function");
- string nameMain = std::get<0>(ClaspLayer::parse<std::string>(model.begin()->second));
+ string nameMain = std::get<0>(TranscendLayer::parse<std::string>(model.begin()->second));
compilation::IFunctionUnit* unitMain = getFunctionUnit(man->root->findFunction(nameMain));
entry = unitMain->compile();
}
llvm::Function*
CompilePass::getEntryFunction() {
assert(entry);
return entry;
}
void
-CompilePass::prepareQueries(ClaspLayer* clasp) {
- clasp->registerQuery(new containers::Query(), QueryId::ContainersQuery);
- clasp->registerQuery(new polymorph::PolymorphQuery(), QueryId::PolymorphQuery);
+CompilePass::prepareQueries(TranscendLayer* transcend) {
+ transcend->registerQuery(new containers::Query(), QueryId::ContainersQuery);
+ transcend->registerQuery(new polymorph::PolymorphQuery(), QueryId::PolymorphQuery);
}
} //end of namespace xreate
/**
* \class xreate::CompilePass
* \brief Encapsulates all compilation activities
*
- * xreate::CompilePass iterates over xreate::AST tree and produces executable code fed by data(via xreate::Attachments) gathered by previous passes as well as data via queries(xreate::IQuery) from xreate:ClaspLayer reasoner.
+ * xreate::CompilePass iterates over xreate::AST tree and produces executable code fed by data(via xreate::Attachments) gathered by previous passes as well as data via queries(xreate::IQuery) from xreate:TranscendLayer reasoner.
* Compilation's done using xreate::LLVMLayer(wrapper over LLVM toolchain) and based on following aspects:
* - Containers support. See \ref compilation/containers.h
* - Late Conext compilation. See xreate::context::LateContextCompiler2
* - Interpretation support. See xreate::interpretation::TargetInterpretation
* - Loop saturation support. See xreate::compilation::TransformerSaturation
* - External Code access. See xreate::ExternLayer(wrapper over Clang library)
*
* \section adaptability_sect Adaptability
* xreate::CompilePass's architecture provides adaptability by employing:
* - %Function Decorators to alter function-level compilation. See xreate::compilation::IFunctionUnit
* - Code Block Decorators to alter code block level compilation. See xreate::compilation::ICodeScopeUnit
* Default functionality defined by \ref xreate::compilation::DefaultCodeScopeUnit
* - Targets to allow more versitile extensions.
* Currently only xreate::interpretation::TargetInterpretation use Targets infrastructure. See xreate::compilation::Target
* - %Altering Function invocation. xreate::compilation::ICallStatement
*
* Client able to construct compiler with desired decorators using xreate::compilation::CompilePassCustomDecorators.
* As a handy alias, `CompilePassCustomDecorators<void, void>` constructs default compiler
*
*/
diff --git a/cpp/src/pass/compilepass.h b/cpp/src/pass/compilepass.h
index a21db70..405aac0 100644
--- a/cpp/src/pass/compilepass.h
+++ b/cpp/src/pass/compilepass.h
@@ -1,207 +1,207 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
*
* compilepass.h
*/
#ifndef COMPILEPASS_H
#define COMPILEPASS_H
#include "abstractpass.h"
#include "llvm/IR/Function.h"
namespace xreate {
- class ClaspLayer;
+ class TranscendLayer;
class CompilePass;
class LLVMLayer;
namespace interpretation{
class TargetInterpretation;
}
}
namespace xreate { namespace compilation {
class ICodeScopeUnit;
class IFunctionUnit;
class TransformationsManager;
/** \brief Holds current position in %AST while traversing*/
struct Context{
ICodeScopeUnit* scope;
IFunctionUnit* function;
CompilePass* pass;
};
/** \brief Interface to specify custom way of function invocation
* \details Default implementation is xreate::compilation::CallStatementRaw
*/
class ICallStatement {
public:
/** \brief Returns result of custom function invocation for given arguments*/
virtual llvm::Value* operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl="") = 0;
};
/** \brief Default ICallStatement implementation */
class CallStatementRaw: public ICallStatement{
public:
CallStatementRaw(llvm::Function* callee, LLVMLayer* l)
: __callee(callee), __calleeTy(callee->getFunctionType()), llvm(l) {}
CallStatementRaw(llvm::Value* callee, llvm::FunctionType* ty, LLVMLayer* l)
: __callee(callee), __calleeTy(ty), llvm(l) {}
/** \brief Makes type conversions and returns LLVM call statement with given arguments*/
llvm::Value* operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl="");
private:
llvm::Value* __callee;
llvm::FunctionType* __calleeTy;
LLVMLayer* llvm;
};
/** \brief Interface to allow modification of CodeScope compilation
* \details Default implementation defined in xreate::compilation::DefaultCodeScopeUnit
*/
class ICodeScopeUnit{
public:
CompilePass* const pass;
IFunctionUnit* const function;
const CodeScope* const scope;
llvm::BasicBlock* currentBlockRaw;
ICodeScopeUnit(const CodeScope* const codeScope, IFunctionUnit* f, CompilePass* compilePass);
virtual ~ICodeScopeUnit();
virtual llvm::Value* compile(const std::string& hintBlockDecl="")=0;
virtual llvm::Value* processSymbol(const Symbol& s, std::string hintRetVar="")=0;
virtual llvm::Value* process(const Expression& expr, const std::string& hintVarDecl="")=0;
virtual Symbol bindArg(llvm::Value* value, std::string&& alias)=0;
virtual void bindArg(llvm::Value* value, const ScopedSymbol& s)=0;
protected:
virtual ICallStatement* findFunction(const Expression& opCall)=0;
};
/** \brief Minimal useful ICodeScopeUnit implementation suited for inheritance */
class BasicCodeScopeUnit: public ICodeScopeUnit{
public:
BasicCodeScopeUnit(const CodeScope* const codeScope, IFunctionUnit* f, CompilePass* compilePass);
llvm::Value* processSymbol(const Symbol& s, std::string hintRetVar="") override;
llvm::Value* process(const Expression& expr, const std::string& hintVarDecl="") override;
llvm::Value* compile(const std::string& hintBlockDecl="") override;
protected:
ICallStatement* findFunction(const Expression& opCall) override;
};
/** \brief Interface to specify compilation of %Function */
class IFunctionUnit{
public:
IFunctionUnit(ManagedFnPtr f, CompilePass* p): function(f), pass(p) {}
virtual ~IFunctionUnit();
llvm::Function* compile();
ICodeScopeUnit* getEntry();
ICodeScopeUnit* getScopeUnit(const CodeScope * const scope);
ICodeScopeUnit* getScopeUnit(ManagedScpPtr scope);
ManagedFnPtr function;
llvm::Function* raw = nullptr;
protected:
CompilePass* pass=nullptr;
virtual std::string prepareName() = 0;
virtual std::vector<llvm::Type*> prepareArguments() = 0;
virtual llvm::Type* prepareResult() = 0;
virtual llvm::Function::arg_iterator prepareBindings() = 0;
private:
std::map<const CodeScope * const, std::weak_ptr<ICodeScopeUnit>> __scopes;
std::list<std::shared_ptr<ICodeScopeUnit>> __orphanedScopes;
};
/** \brief Minimal useful IFunctionUnit implementation suited for inheritance */
class BasicFunctionUnit: public IFunctionUnit{
public:
BasicFunctionUnit(ManagedFnPtr f, CompilePass* p)
: IFunctionUnit(f, p) {}
protected:
std::string prepareName() override;
virtual std::vector<llvm::Type*> prepareArguments() override;
virtual llvm::Type* prepareResult() override;
virtual llvm::Function::arg_iterator prepareBindings() override;
};
} // end of namespace compilation
class CompilePass : public AbstractPass<void> {
friend class compilation::BasicCodeScopeUnit;
friend class compilation::IFunctionUnit;
public:
compilation::TransformationsManager* managerTransformations;
interpretation::TargetInterpretation* targetInterpretation;
CompilePass(PassManager* manager): AbstractPass<void>(manager) {}
/** \brief Executes compilation process */
void run() override;
/**\brief Returns compiled specified %Function
* \details Executes function compilation or read cache if it's already done
*/
compilation::IFunctionUnit* getFunctionUnit(const ManagedFnPtr& function);
/**\brief Returns compiled main(entry) %Function in program */
llvm::Function* getEntryFunction();
- /** \brief Initializes queries required by compiler. See xreate::IQuery, xreate::ClaspLayer */
- static void prepareQueries(ClaspLayer* clasp);
+ /** \brief Initializes queries required by compiler. See xreate::IQuery, xreate::TranscendLayer */
+ static void prepareQueries(TranscendLayer* transcend);
protected:
virtual compilation::IFunctionUnit* buildFunctionUnit(const ManagedFnPtr& function)=0;
virtual compilation::ICodeScopeUnit* buildCodeScopeUnit(const CodeScope* const scope, compilation::IFunctionUnit* function)=0;
private:
//TODO free `functions` in destructor
std::map<unsigned int, compilation::IFunctionUnit*> functions;
llvm::Function* entry = 0;
};
namespace compilation{
/** \brief Constructs compiler with desired %Function and %Code Scope decorators. See adaptability in xreate::CompilePass*/
template<class FUNCTION_DECORATOR=void, class SCOPE_DECORATOR=void>
class CompilePassCustomDecorators: public ::xreate::CompilePass{
public:
CompilePassCustomDecorators(PassManager* manager): ::xreate::CompilePass(manager) {}
virtual compilation::IFunctionUnit* buildFunctionUnit(const ManagedFnPtr& function) override{
return new FUNCTION_DECORATOR(function, this);
}
virtual compilation::ICodeScopeUnit* buildCodeScopeUnit(const CodeScope* const scope, IFunctionUnit* function) override{
return new SCOPE_DECORATOR(scope, function, this);
}
};
template<>
compilation::IFunctionUnit*
CompilePassCustomDecorators<void, void>::buildFunctionUnit(const ManagedFnPtr& function);
template<>
compilation::ICodeScopeUnit*
CompilePassCustomDecorators<void, void>::buildCodeScopeUnit(const CodeScope* const scope, IFunctionUnit* function);
}} //end of namespace xreate::compilation
#endif // COMPILEPASS_H
diff --git a/cpp/src/pass/dfapass.cpp b/cpp/src/pass/dfapass.cpp
index 7beb72f..a4a6747 100644
--- a/cpp/src/pass/dfapass.cpp
+++ b/cpp/src/pass/dfapass.cpp
@@ -1,233 +1,233 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
*
* dfapass.cpp
*/
/**
* \file dfapass.h
* \brief Data Flow Analysis(DFA)
*/
//DEBT DFA represent VersionaPass in declarative form using applyDependencies
// applyDependencies(expression, context, cache, decl);
//DEBT DFA prepare static annotations and represent InterpretationPass in declarative form
// applyStaticAnnotations(expression, context, cache, decl);
//DEBT DFA Eliminate dfa schemes
#include "pass/dfapass.h"
#include "xreatemanager.h"
-#include "clasplayer.h"
+#include "transcendlayer.h"
#include <boost/format.hpp>
#include <boost/variant/variant.hpp>
using namespace std;
namespace xreate {namespace dfa {
DFAPass::DFAPass(PassManager* manager)
: AbstractPass(manager)
, graph{new DFAGraph()}
-, clasp(manager->clasp) { }
+, transcend(manager->transcend) { }
void
DFAPass::processCallInstance(const Expression& expr, PassContext context, const SymbolNode& result) {
const string &nameCalleeFunction=expr.getValueString();
//TODO implement processFnCall/Uncertain
list<ManagedFnPtr> variantsCalleeFunction=man->root->getFunctionSpecializations(nameCalleeFunction);
vector<SymbolNode> operands;
operands.reserve(expr.getOperands().size());
for(const Expression& arg : expr.getOperands()) {
operands.push_back(process(arg, context));
}
//Set calling relations:
DFACallInstanceType type=variantsCalleeFunction.size()>1?WEAK:STRONG;
for(ManagedFnPtr function : variantsCalleeFunction) {
CodeScope *scopeRemote=function->getEntryScope();
DFACallInstance callInstance;
callInstance.fnName=function->getName();
callInstance.type=type;
std::vector<SymbolNode>::const_iterator nodeActual=operands.begin();
for(const std::string &identFormal : scopeRemote->__bindings) {
const ScopedSymbol symbolFormal{scopeRemote->__identifiers.at(identFormal), versions::VERSION_NONE};
- SymbolPacked symbolFormalPacked=clasp->pack(Symbol{symbolFormal, scopeRemote}, nameCalleeFunction+":"+identFormal);
+ SymbolPacked symbolFormalPacked=transcend->pack(Symbol{symbolFormal, scopeRemote}, nameCalleeFunction+":"+identFormal);
callInstance.args.push_back(std::make_pair(symbolFormalPacked, *nodeActual));
++nodeActual;
}
callInstance.retActual=result;
- SymbolNode retFormal=SymbolNode(clasp->pack(Symbol{ScopedSymbol::RetSymbol, scopeRemote}, nameCalleeFunction+":[ret]"));
+ SymbolNode retFormal=SymbolNode(transcend->pack(Symbol{ScopedSymbol::RetSymbol, scopeRemote}, nameCalleeFunction+":[ret]"));
graph->addCallInstance(std::move(callInstance));
}
}
void
DFAPass::processDependencies(const SymbolNode& node, const Expression& expression, PassContext context, ProcessingCache& cache) {
cache.operands.reserve(expression.getOperands().size());
for(const Expression &op : expression.getOperands()) {
const SymbolNode& subnodeOperand=process(op, context);
cache.operands.push_back(subnodeOperand);
graph->addDependency(node, subnodeOperand);
}
cache.blocks.reserve(expression.blocks.size());
for(CodeScope* block : expression.blocks) {
const SymbolNode& subnodeBlock=process(block, context);
cache.blocks.push_back(subnodeBlock);
graph->addDependency(node, subnodeBlock);
}
}
SymbolNode
DFAPass::process(const Expression& expression, PassContext context, const std::string& varDecl) {
SymbolNode result;
if(Attachments::exists<SymbolAlias>(expression)){
Symbol varSymbol=Attachments::get<SymbolAlias>(expression);
- result=clasp->pack(varSymbol, varDecl);
+ result=transcend->pack(varSymbol, varDecl);
} else if(expression.__state==Expression::IDENT&&expression.tags.size()==0){
Symbol varSymbol=Attachments::get<IdentifierSymbol>(expression);
- result=clasp->pack(varSymbol, expression.getValueString());
+ result=transcend->pack(varSymbol, expression.getValueString());
} else {
result=SymbolAnonymous{expression.id};
}
graph->printInplaceAnnotations(result, expression);
switch(expression.__state) {
case Expression::COMPOUND: {
switch(expression.op) {
case Operator::CALL: {
processCallInstance(expression, context, result);
break;
}
case Operator::IF: {
const SymbolNode& scopeA=process(expression.blocks.front(), context, "ifTrue" + std::to_string(expression.id));
const SymbolNode& scopeB=process(expression.blocks.back(), context, "ifFalse" + std::to_string(expression.id));
const SymbolNode& condition=process(expression.operands.at(0), context);
graph->addDependency(result, scopeA);
graph->addDependency(result, scopeB);
graph->addDependency(result, condition);
graph->printWeakAlias(result, scopeA);
graph->printWeakAlias(result, scopeB);
break;
}
case Operator::SWITCH:
case Operator::SWITCH_VARIANT: {
for(CodeScope* block : expression.blocks) {
const SymbolNode& subnodeBlock=process(block, context, "case"+to_string(block->getBody().id));
graph->addDependency(result, subnodeBlock);
graph->printWeakAlias(result, subnodeBlock);
}
const SymbolNode& condition=process(expression.operands.at(0), context);
graph->addDependency(result, condition);
break;
}
default: {
ProcessingCache cache;
processDependencies(result, expression, context, cache);
break;
}
}
break;
}
case Expression::IDENT: {
SymbolNode symbIdent=AbstractPass<SymbolNode>::process(expression, context, varDecl);
if(!(result==symbIdent)){
graph->addDependency(result, symbIdent);
graph->printAlias(result, symbIdent);
}
break;
}
case Expression::NUMBER:
case Expression::STRING: {
break;
}
case Expression::INVALID:
case Expression::BINDING: {
assert(false);
break;
}
}
return result;
}
SymbolNode
DFAPass::process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl) {
if (!hintBlockDecl.empty()) {
Symbol symbRet{ScopedSymbol::RetSymbol, scope};
- clasp->pack(symbRet, hintBlockDecl + ":[ret]");
+ transcend->pack(symbRet, hintBlockDecl + ":[ret]");
}
for(const std::string& binding : scope->__bindings) {
Symbol bindingSymbol{scope->getSymbol(binding), scope};
- SymbolPacked bindingPacked=clasp->pack(bindingSymbol, binding);
+ SymbolPacked bindingPacked=transcend->pack(bindingSymbol, binding);
getSymbolCache().setCachedValue(bindingSymbol, SymbolNode(bindingPacked));
}
return AbstractPass<SymbolNode>::process(scope, context, hintBlockDecl);
}
SymbolNode
DFAPass::process(ManagedFnPtr function) {
- clasp->pack(Symbol{ScopedSymbol::RetSymbol, function->getEntryScope()}, function->getName()+to_string(function.id())+":[ret]");
+ transcend->pack(Symbol{ScopedSymbol::RetSymbol, function->getEntryScope()}, function->getName()+to_string(function.id())+":[ret]");
SymbolNode result=AbstractPass<SymbolNode>::process(function);
graph->printFunctionRet(function, result);
return result;
}
void
DFAPass::finish() {
- clasp->registerReport(graph);
+ transcend->registerReport(graph);
//Declare symbols:
- graph->printSymbols(clasp);
+ graph->printSymbols(transcend);
AbstractPass::finish();
}
} //end of namespace dfa
template<>
SymbolNode
defaultValue() {
assert(false);
}
} //end of xreate namespace
/**
* \class xreate::dfa::DFAPass
* \details Provides DFA, important analysis for reasoning. Iterates over AST and stores collected data in DFAGraph
*/
diff --git a/cpp/src/pass/dfapass.h b/cpp/src/pass/dfapass.h
index 51b3eb1..09f5538 100644
--- a/cpp/src/pass/dfapass.h
+++ b/cpp/src/pass/dfapass.h
@@ -1,51 +1,51 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
*
* dfapass.h
* Data Flow Graph building pass
*/
#ifndef DFGPASS_H
#define DFGPASS_H
#include "abstractpass.h"
#include "analysis/dfagraph.h"
namespace xreate {
- class ClaspLayer;
+ class TranscendLayer;
}
namespace xreate { namespace dfa {
struct ProcessingCache {
std::vector<SymbolNode> operands;
std::vector<SymbolNode> blocks;
};
/** \brief Data Flow Analysis Pass(%DFA) */
class DFAPass: public AbstractPass<SymbolNode> {
public:
DFAPass(PassManager* manager);
protected:
virtual SymbolNode process(const Expression& expression, PassContext context, const std::string& varDecl="") override;
virtual SymbolNode process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl="") override;
virtual SymbolNode process(ManagedFnPtr function) override;
void init();
void finish() override;
private:
void processCallInstance(const Expression& expr, PassContext context, const SymbolNode& result);
void processDependencies(const SymbolNode& node, const Expression& expression, PassContext context, ProcessingCache& cache);
DFAGraph* graph;
- ClaspLayer* clasp;
+ TranscendLayer* transcend;
};
}} //end of xreate::dfa namespace
#endif
diff --git a/cpp/src/pass/interpretationpass.cpp b/cpp/src/pass/interpretationpass.cpp
index 5e75aea..5e8a0e3 100644
--- a/cpp/src/pass/interpretationpass.cpp
+++ b/cpp/src/pass/interpretationpass.cpp
@@ -1,525 +1,525 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: interpretationpass.cpp
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on July 5, 2016, 5:21 PM
*/
/**
* \file interpretationpass.h
* \brief Interpretation analysis: determines what parts of code could be interpreted
*/
#include "pass/interpretationpass.h"
#include <compilation/targetinterpretation.h>
#include <bits/stl_vector.h>
#include "ast.h"
-//DEBT implement InterpretationPass purely in clasp
+//DEBT implement InterpretationPass purely in transcend
//DEBT represent InterpretationPass as general type inference
using namespace std;
namespace xreate {
template<>
interpretation::InterpretationResolution
defaultValue<interpretation::InterpretationResolution>() {
return interpretation::CMPL_ONLY;
}
namespace interpretation {
enum InterpretationQuery {
QUERY_INTR_ONLY, QUERY_CMPL_ONLY
};
namespace details {
template<InterpretationQuery FLAG_REQUIRED>
bool
checkConstraints(InterpretationResolution flag) {
return( (flag==INTR_ONLY&&FLAG_REQUIRED==QUERY_INTR_ONLY)
||(flag==CMPL_ONLY&&FLAG_REQUIRED==QUERY_CMPL_ONLY));
}
InterpretationResolution
recognizeTags(const map<std::string, Expression>& tags) {
auto i=tags.find("interpretation");
if(i==tags.end()){
return ANY;
}
assert(i->second.op==Operator::CALL);
const string& cmd=i->second.operands.at(0).getValueString();
//TODO make consistent names of annotation and resolution
if(cmd=="force"){
return INTR_ONLY;
} else if(cmd=="suppress"){
return CMPL_ONLY;
}
return ANY;
}
}
InterpretationResolution
unify(InterpretationResolution flag) {
return flag;
}
template<typename FLAG_A, typename FLAG_B, typename... FLAGS>
InterpretationResolution
unify(FLAG_A flagA, FLAG_B flagB, FLAGS... flags) {
if(flagA==ANY){
return unify(flagB, flags...);
}
if(flagB==ANY){
return unify(flagA, flags...);
}
assert(flagA==flagB);
return flagA;
}
template<InterpretationQuery FLAG_REQUIRED>
bool
checkConstraints(std::vector<InterpretationResolution>&& flags) {
assert(flags.size());
InterpretationResolution flag=flags.front();
return details::checkConstraints<FLAG_REQUIRED>(flag);
}
template<InterpretationQuery FLAG_REQUIRED_A, InterpretationQuery FLAG_REQUIRED_B, InterpretationQuery... FLAGS>
bool
checkConstraints(std::vector<InterpretationResolution>&& flags) {
assert(flags.size());
InterpretationResolution flag=flags.front();
flags.pop_back();
if(details::checkConstraints<FLAG_REQUIRED_A>(flag)){
return checkConstraints<FLAG_REQUIRED_B, FLAGS...>(move(flags));
}
return false;
}
bool
InterpretationData::isDefault() const {
return(resolution==ANY&&op==NONE);
}
void
recognizeTags(const Expression& e) {
InterpretationData tag{details::recognizeTags(e.tags), NONE};
if(!tag.isDefault())
Attachments::put<InterpretationData>(e, tag);
}
InterpretationResolution
recognizeTags(const ManagedFnPtr& f) {
return details::recognizeTags(f->getTags());
}
InterpretationPass::InterpretationPass(PassManager* manager)
: AbstractPass(manager) {
Attachments::init<FunctionInterpretationData>();
Attachments::init<InterpretationData>();
}
void
InterpretationPass::run() {
ManagedFnPtr f=man->root->begin<Function>();
auto& visitedSymbols=getSymbolCache();
while(f.isValid()) {
const Symbol&symbolFunction{ScopedSymbol::RetSymbol, f->getEntryScope()};
if(!visitedSymbols.isCached(symbolFunction)){
visitedSymbols.setCachedValue(symbolFunction, process(f));
}
++f;
}
}
InterpretationResolution
InterpretationPass::process(const Expression& expression, PassContext context, const std::string& decl) {
recognizeTags(expression);
InterpretationResolution resolution=ANY;
InterpretationOperator op=NONE;
switch(expression.__state) {
case Expression::NUMBER:
case Expression::STRING:
{
break;
}
case Expression::IDENT:
{
resolution=Parent::processSymbol(Attachments::get<IdentifierSymbol>(expression), context);
break;
}
case Expression::COMPOUND:
break;
default:
{
resolution=CMPL_ONLY;
break;
}
}
if(expression.__state==Expression::COMPOUND)
switch(expression.op) {
case Operator::EQU:
case Operator::NE:
{
InterpretationResolution left=process(expression.operands[0], context);
InterpretationResolution right=process(expression.operands[1], context);
resolution=unify(left, right);
break;
}
case Operator::LOGIC_AND:
{
assert(expression.operands.size()==1);
resolution=process(expression.operands[0], context);
break;
}
case Operator::CALL:
{
//TODO cope with static/dynamic context
//TODO BUG here: if several variants they all are processed as CMPL regardless of signature
list<ManagedFnPtr> callees=man->root->getFunctionSpecializations(expression.getValueString());
if(callees.size()!=1){
resolution=CMPL_ONLY;
break;
}
ManagedFnPtr callee=callees.front();
const Symbol& symbCalleeFunc{ScopedSymbol::RetSymbol, callee->getEntryScope()};
//recursion-aware processing:
// - skip self recursion
const Symbol&symbSelfFunc{ScopedSymbol::RetSymbol, context.function->getEntryScope()};
if(!(symbSelfFunc==symbCalleeFunc)){
InterpretationResolution resCallee=processFnCall(callee, context);
assert(resCallee!=FUNC_POSTPONED&&"Indirect recursion detected: can't decide on interpretation resolution");
resolution=unify(resolution, resCallee);
}
//check arguments compatibility
const FunctionInterpretationData& calleeSignature=FunctionInterpretationHelper::getSignature(callee);
for(size_t op=0, size=expression.operands.size(); op<size; ++op) {
const Expression &operand=expression.operands[op];
InterpretationResolution argActual=process(operand, context);
InterpretationResolution argExpected=calleeSignature.signature[op];
//TODO use args unification result to properly process function call
unify(argActual, argExpected);
}
if(FunctionInterpretationHelper::needPartialInterpretation(callee)){
op=CALL_INTERPRET_PARTIAL;
}
break;
}
case Operator::CALL_INTRINSIC:
{
std::string nameFunction=expression.getValueString();
if(nameFunction=="query"){
resolution=INTR_ONLY;
} else if(nameFunction=="query_scope") {
resolution=INTR_ONLY;
} else {
resolution=CMPL_ONLY;
}
break;
}
case Operator::IF:
{
InterpretationResolution flagCondition=process(expression.getOperands()[0], context);
InterpretationResolution flagScope1=Parent::process(expression.blocks.front(), context);
InterpretationResolution flagScope2=Parent::process(expression.blocks.back(), context);
//special case: IF_INTERPRET_CONDITION
if(checkConstraints<QUERY_INTR_ONLY>({flagCondition})){
op=IF_INTERPRET_CONDITION;
flagCondition=ANY;
}
resolution=unify(flagCondition, flagScope1, flagScope2);
break;
}
case Operator::FOLD:
{
InterpretationResolution flagInput=process(expression.getOperands()[0], context);
InterpretationResolution flagAccumInit=process(expression.getOperands()[1], context);
CodeScope* scopeBody=expression.blocks.front();
const std::string& nameEl=expression.bindings[0];
Symbol symbEl{ScopedSymbol
{scopeBody->__identifiers.at(nameEl), versions::VERSION_NONE}, scopeBody};
getSymbolCache().setCachedValue(symbEl, InterpretationResolution(flagInput));
const std::string& nameAccum=expression.bindings[1];
Symbol symbAccum{ScopedSymbol
{scopeBody->__identifiers.at(nameAccum), versions::VERSION_NONE}, scopeBody};
getSymbolCache().setCachedValue(symbAccum, InterpretationResolution(flagAccumInit));
InterpretationResolution flagBody=Parent::process(expression.blocks.front(), context);
//special case: FOLD_INTERPRET_INPUT
if(checkConstraints<QUERY_INTR_ONLY>({flagInput})){
op=FOLD_INTERPRET_INPUT;
flagInput=ANY;
}
resolution=unify(flagInput, flagAccumInit, flagBody);
break;
}
case Operator::INDEX:
{
for(const Expression &op : expression.getOperands()) {
resolution=unify(resolution, process(op, context));
}
break;
}
case Operator::SWITCH:
{
InterpretationResolution flagCondition=process(expression.operands[0], context);
bool hasDefaultCase=expression.operands[1].op==Operator::CASE_DEFAULT;
//determine conditions resolution
InterpretationResolution flagHeaders=flagCondition;
for(size_t size=expression.operands.size(), i=hasDefaultCase?2:1; i<size; ++i) {
const Expression& exprCase=expression.operands[i];
flagHeaders=unify(flagHeaders, Parent::process(exprCase.blocks.front(), context));
}
if(checkConstraints<QUERY_INTR_ONLY>({flagHeaders})){
op=SWITCH_INTERPRET_CONDITION;
flagHeaders=ANY;
}
//determine body resolutions
resolution=flagHeaders;
for(size_t size=expression.operands.size(), i=1; i<size; ++i) {
const Expression& exprCase=expression.operands[i];
resolution=unify(resolution, Parent::process(exprCase.blocks.back(), context));
}
break;
}
case Operator::SWITCH_VARIANT:
{
InterpretationResolution resolutionCondition=process(expression.operands.at(0), context);
resolution=resolutionCondition;
if(checkConstraints<QUERY_INTR_ONLY>({resolution})){
op=SWITCH_VARIANT;
resolution=ANY;
}
const string identCondition=expression.bindings.front();
for(auto scope : expression.blocks) {
//set binding resolution
ScopedSymbol symbolInternal=scope->getSymbol(identCondition);
getSymbolCache().setCachedValue(Symbol{symbolInternal, scope}, InterpretationResolution(resolutionCondition));
resolution=unify(resolution, Parent::process(scope, context));
}
for(auto scope : expression.blocks) {
resolution=unify(resolution, Parent::process(scope, context));
}
break;
}
case Operator::LIST:
case Operator::LIST_NAMED:
{
for(const Expression &op : expression.getOperands()) {
resolution=unify(resolution, process(op, context));
}
break;
}
case Operator::VARIANT:
{
if(expression.getOperands().size()){
resolution=process(expression.getOperands().front(), context);
} else {
resolution=ANY;
}
break;
}
default:
{
resolution=CMPL_ONLY;
for(const Expression &op : expression.getOperands()) {
process(op, context);
}
for(CodeScope* scope : expression.blocks) {
Parent::process(scope, context);
}
break;
}
}
InterpretationData dataExpected=
Attachments::get<InterpretationData>(expression,{ANY, NONE});
resolution=unify(resolution, dataExpected.resolution);
if(resolution!=dataExpected.resolution || op != dataExpected.op ){
Attachments::put<InterpretationData>(expression,{resolution, op});
}
return resolution;
}
InterpretationResolution
InterpretationPass::processFnCall(ManagedFnPtr function, PassContext context) {
return process(function);
}
InterpretationResolution
InterpretationPass::process(ManagedFnPtr function) {
CodeScope* entry=function->getEntryScope();
std::vector<std::string> arguments=entry->__bindings;
const Symbol&symbSelfFunc{ScopedSymbol::RetSymbol, function->getEntryScope()};
auto& cache=getSymbolCache();
if(cache.isCached(symbSelfFunc))
return cache.getCachedValue(symbSelfFunc);
const FunctionInterpretationData& fnSignature=FunctionInterpretationHelper::getSignature(function);
InterpretationResolution fnResolutionExpected=details::recognizeTags(function->getTags());
//mark preliminary function resolution as expected
if(fnResolutionExpected!=ANY){
cache.setCachedValue(symbSelfFunc, move(fnResolutionExpected));
} else {
// - in order to recognize indirect recursion mark this function resolution as POSTPONED
cache.setCachedValue(symbSelfFunc, FUNC_POSTPONED);
}
//set resolution for function arguments as expected
for(int argNo=0, size=arguments.size(); argNo<size; ++argNo) {
Symbol symbArg{ScopedSymbol
{entry->__identifiers.at(arguments[argNo]), versions::VERSION_NONE}, entry};
cache.setCachedValue(symbArg, InterpretationResolution(fnSignature.signature[argNo]));
}
PassContext context;
context.function=function;
context.scope=entry;
InterpretationResolution resActual=process(CodeScope::getDefinition(symbSelfFunc), context);
resActual=unify(resActual, fnResolutionExpected);
return cache.setCachedValue(symbSelfFunc, move(resActual));
}
const FunctionInterpretationData
FunctionInterpretationHelper::getSignature(ManagedFnPtr function) {
if(Attachments::exists<FunctionInterpretationData>(function)){
return Attachments::get<FunctionInterpretationData>(function);
}
FunctionInterpretationData&& data=recognizeSignature(function);
Attachments::put<FunctionInterpretationData>(function, data);
return data;
}
FunctionInterpretationData
FunctionInterpretationHelper::recognizeSignature(ManagedFnPtr function) {
CodeScope* entry=function->__entry;
FunctionInterpretationData result;
result.signature.reserve(entry->__bindings.size());
bool flagPartialInterpretation=false;
for(size_t no=0, size=entry->__bindings.size(); no<size; ++no) {
const std::string& argName=entry->__bindings[no];
Symbol symbArg{ScopedSymbol
{entry->__identifiers.at(argName), versions::VERSION_NONE}, entry};
const Expression& arg=CodeScope::getDefinition(symbArg);
InterpretationResolution argResolution=details::recognizeTags(arg.tags);
flagPartialInterpretation|=(argResolution==INTR_ONLY);
result.signature.push_back(argResolution);
}
result.flagPartialInterpretation=flagPartialInterpretation;
return result;
}
bool
FunctionInterpretationHelper::needPartialInterpretation(ManagedFnPtr function) {
const FunctionInterpretationData& data=getSignature(function);
return data.flagPartialInterpretation;
}
}
} //end of namespace xreate::interpretation
/** \class xreate::interpretation::InterpretationPass
*
* Encapsulates *Interpretation Analysis* to support [Interpretation Concept](/w/concepts/dfa)
*
* Recognizes program functions, expressions, instructions eligible for interpretation
* and stores output in Attachments<FunctionInterpretationData> and Attachments<InterpretationData>
*
* There are number of instructions currently able to be interpreted:
* - Basic literals: numbers and strings
* - Compounds: lists, structs, variants
* - Non-versioned identifiers
* - Comparison and logic operators
* - %Function calls
* - `query` intrinsic function calls
* - Branching: `if`, `loop fold`, `switch`, `switch variant` statements
*
* Some of those instructions are eligibile for *hybrid interpretation* to allow coupling
* of compiled instructions with interpreted ones, those are:
* - Partial function calls
* - Branching: `if`, `loop fold`, `switch`, `switch variant` statements
*
* \sa xreate::interpretation::TargetInterpretation, [Interpretation Concept](/w/concepts/dfa)
- */
\ No newline at end of file
+ */
diff --git a/cpp/src/pass/versionspass.cpp b/cpp/src/pass/versionspass.cpp
index 7071147..8129686 100644
--- a/cpp/src/pass/versionspass.cpp
+++ b/cpp/src/pass/versionspass.cpp
@@ -1,375 +1,376 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* versionspass.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on January 4, 2017, 3:13 PM
*/
/** \class xreate::versions::VersionsPass
* Has two parts:
* - Validates correctness of versioned variables with regard to variables lifespan
* - Determines versioned variables computation order
* \sa VersionsScopeDecorator, VersionsGraph, [Versions Concept](/w/concepts/versions)
*/
#include <boost/optional/optional.hpp>
#include "pass/versionspass.h"
namespace std{
std::size_t
hash<xreate::versions::SymbolOrPlaceholder>::operator()(xreate::versions::SymbolOrPlaceholder const& s) const
{return std::hash<xreate::Symbol>()(s.symbol) + (s.flagEndOfLifePlaceholder? 9849 : 1);}
bool
equal_to<xreate::versions::SymbolOrPlaceholder>::operator()(const xreate::versions::SymbolOrPlaceholder& __x, const xreate::versions::SymbolOrPlaceholder& __y) const
{ return __x.flagEndOfLifePlaceholder == __y.flagEndOfLifePlaceholder && __x.symbol == __y.symbol; }
}
using namespace std;
+namespace xreate {
+ template<>
+ std::list<Symbol>
+ defaultValue<std::list<Symbol>>(){
+ return std::list<Symbol>();
+ };
+}
namespace xreate{ namespace versions{
-template<>
-std::list<Symbol>
-defaultValue<std::list<Symbol>>(){
- return std::list<Symbol>();
-};
-
inline std::string
printSymbol(const SymbolOrPlaceholder& s){
switch(s.flagEndOfLifePlaceholder){
case SYMBOL: return string("(") + std::to_string(s.symbol.identifier.id) + ", "+ std::to_string(s.symbol.identifier.version) + ")";
case PLACEHOLDER: return string("(") + std::to_string(s.symbol.identifier.id) + ", "+ std::to_string(s.symbol.identifier.version) + ")+";
}
return "";
}
void
VersionsGraph::__debug_print(std::ostream& output) const{
for(auto entry: __inferiors){
output << printSymbol(entry.second) << " <-" << printSymbol(entry.first) << "\n";
}
}
void
VersionsGraph::defineEndOfLife(const Symbol& symbol, const Symbol& symbolSuccessor){
if(__dictSuccessors.count(symbol)){
assert("No version branches allowed yet" && false);
}
const SymbolOrPlaceholder& placeholder = getEndOfLife(symbol);
auto inferiorsDeferred = __inferiors.equal_range(placeholder);
std::unordered_multimap<SymbolOrPlaceholder, SymbolOrPlaceholder> inferiorsReassigned;
for (const auto& inf: boost::make_iterator_range(inferiorsDeferred)){
inferiorsReassigned.emplace(SymbolOrPlaceholder{SYMBOL, symbolSuccessor}, inf.second);
}
__inferiors.erase(placeholder);
__inferiors.insert(inferiorsReassigned.begin(), inferiorsReassigned.end());
__inferiors.emplace(SymbolOrPlaceholder{SYMBOL, symbolSuccessor}, SymbolOrPlaceholder{SYMBOL, symbol});
__dictSuccessors.emplace(symbol, symbolSuccessor);
}
SymbolOrPlaceholder
VersionsGraph::getEndOfLife(const Symbol& s){
if (__dictSuccessors.count(s)){
return SymbolOrPlaceholder{SYMBOL, __dictSuccessors.at(s)}; }
return SymbolOrPlaceholder{PLACEHOLDER, s};
}
void
VersionsGraph::applyNatualDependencies(const Symbol& symbol, const std::list<Symbol>& dependencies){
for (const Symbol& right: dependencies){
__inferiorsNatural.emplace(symbol, right);
}
}
void
VersionsGraph::applyDependentEndOfLife(const SymbolOrPlaceholder& symbol, const list<Symbol>& dependencies){
for (const Symbol& right: dependencies){
auto rightEOF = getEndOfLife(right);
__inferiors.emplace(rightEOF, symbol);
}
}
bool
VersionsGraph::tryEliminateEofAliases(const std::list<SymbolOrPlaceholder>& aliases){
if (aliases.size()==1){
return true;
}
boost::optional<Symbol> symbolActualEoF;
for(const SymbolOrPlaceholder alias: aliases){
switch(alias.flagEndOfLifePlaceholder){
case SYMBOL:
if(symbolActualEoF){
return false;
}
symbolActualEoF = alias.symbol;
break;
case PLACEHOLDER:
continue;
}
}
if(!symbolActualEoF){
return false;
}
for(const SymbolOrPlaceholder alias: aliases){
switch(alias.flagEndOfLifePlaceholder){
case SYMBOL:
continue;
case PLACEHOLDER:
defineEndOfLife(alias.symbol, symbolActualEoF.get());
break;
}
}
return true;
}
std::list<SymbolOrPlaceholder>
VersionsGraph::extractCycle(const Path& path, const SymbolOrPlaceholder& symbolBeginning){
unsigned int posBeginning = path.at(symbolBeginning);
std::list<SymbolOrPlaceholder> result;
auto i=path.begin();
while(true){
i = std::find_if(i, path.end(), [&posBeginning](const auto& el){return el.second >=posBeginning;});
if (i!= path.end()){
result.push_back(i->first);
++i;
} else {break; }
}
return result;
}
bool
VersionsGraph::validateCycles(const SymbolOrPlaceholder& s,
std::unordered_multimap<SymbolOrPlaceholder, SymbolOrPlaceholder>& graph,
std::unordered_set<SymbolOrPlaceholder>& symbolsVisited,
Path& path)
{
if (symbolsVisited.count(s)) return true;
symbolsVisited.insert(s);
path.emplace(s, path.size());
if (graph.count(s)){
//iterate over imposed dependencies
auto candidates = graph.equal_range(s);
for (auto candidate = candidates.first; candidate != candidates.second; ++candidate){
if (path.count(candidate->second)) {
std::list<SymbolOrPlaceholder> cycle = extractCycle(path, candidate->second);
if (!tryEliminateEofAliases(cycle)) return false;
continue;
}
if(!validateCycles(candidate->second, graph, symbolsVisited, path)) return false;
}
}
//iterate over natural dependencies
if (s.flagEndOfLifePlaceholder == SYMBOL) {
auto candidates = __inferiorsNatural.equal_range(s.symbol);
for (auto candidate = candidates.first; candidate != candidates.second; ++candidate){
if (path.count(SymbolOrPlaceholder{SYMBOL, candidate->second})){
return false;
}
if(!validateCycles(SymbolOrPlaceholder{SYMBOL,candidate->second}, graph, symbolsVisited, path)) return false;
}
}
//check previous version
if (s.flagEndOfLifePlaceholder == PLACEHOLDER){
const Symbol& candidate = s.symbol;
if (path.count(SymbolOrPlaceholder{SYMBOL, candidate})){
std::list<SymbolOrPlaceholder> cycle = extractCycle(path, SymbolOrPlaceholder{SYMBOL, candidate});
if (!tryEliminateEofAliases(cycle)) return false;
}
if(!validateCycles(SymbolOrPlaceholder{SYMBOL,candidate}, graph, symbolsVisited, path)) return false;
}
path.erase(s);
return true;
}
bool
VersionsGraph::validateCycles(){
std::unordered_set<SymbolOrPlaceholder> symbolsVisited;
Path path;
std::unordered_multimap<SymbolOrPlaceholder, SymbolOrPlaceholder> graph(__inferiors);
std::unordered_multimap<SymbolOrPlaceholder, SymbolOrPlaceholder>::const_iterator s;
for (s = graph.begin(); s != graph.end(); ++s){
if(!validateCycles(s->first, graph, symbolsVisited, path)) return false;
}
return true;
}
bool
VersionsGraph::validate(){
return validateCycles();
}
std::list<Symbol>
VersionsGraph::expandPlaceholder(const SymbolOrPlaceholder& symbol, const Symbol& symbolPrev) const{
std::list<Symbol> result;
switch (symbol.flagEndOfLifePlaceholder){
case SYMBOL:
//skip self-loops
if (symbol.symbol == symbolPrev) return {};
return {symbol.symbol};
case PLACEHOLDER:
for (const auto& entry: boost::make_iterator_range(__inferiors.equal_range(symbol))){
list<Symbol>&& childResult = expandPlaceholder(entry.second, symbolPrev);
result.insert(result.end(), childResult.begin(), childResult.end());
}
if (__dictSuccessors.count(symbol.symbol)){
Symbol knownSuccessor = __dictSuccessors.at(symbol.symbol);
//skip alias loop
if (knownSuccessor == symbolPrev) return {};
for (const auto& entry: boost::make_iterator_range(__inferiors.equal_range(SymbolOrPlaceholder{SYMBOL, knownSuccessor}))){
list<Symbol>&& childResult = expandPlaceholder(entry.second, knownSuccessor);
result.insert(result.end(), childResult.begin(), childResult.end());
}
}
break;
}
return result;
}
AttachmentsContainerDefault<std::list<Symbol>>*
VersionsGraph::representAsAttachments() const {
AttachmentsContainerDefault<std::list<Symbol>>* container = new AttachmentsContainerDefault<std::list<Symbol>>();
std::map<Symbol, std::list<Symbol>> containerData;
for(const auto& entry: __inferiors){
if(entry.first.flagEndOfLifePlaceholder == PLACEHOLDER) continue;
list<Symbol>& infs = containerData[entry.first.symbol];
list<Symbol>&& infsExpanded = expandPlaceholder(entry.second, entry.first.symbol);
infs.insert(infs.begin(), infsExpanded.begin(), infsExpanded.end());
}
for(const auto& entry: containerData){
container->put(entry.first, entry.second);
}
return container;
}
std::list<Symbol>
VersionsPass::process(const Expression& expression, PassContext context, const std::string& hintSymbol){
if (expression.__state == Expression::COMPOUND){
std::list<Symbol> resultDependencies;
for (const Expression &op: expression.getOperands()) {
std::list<Symbol> deps = process(op, context);
resultDependencies.insert(resultDependencies.end(), deps.begin(), deps.end());
}
for (CodeScope* scope: expression.blocks) {
std::list<Symbol> deps = Parent::process(scope, context);
resultDependencies.insert(resultDependencies.end(), deps.begin(), deps.end());
}
return resultDependencies;
}
if (expression.__state == Expression::IDENT){
const Symbol symb = Attachments::get<IdentifierSymbol>(expression);
return processSymbol(symb, context, expression.getValueString());
}
return {};
}
//TODO versions, check (declaration.isDefined()) before processing declaration
list<Symbol>
VersionsPass::processSymbol(const Symbol& symbol, PassContext context, const std::string& hintSymbol){
list<Symbol> result{symbol};
if (__symbolsVisited.exists(symbol)){
return result;
}
enum {MODE_ALIAS, MODE_COPY } mode = MODE_ALIAS;
const Expression& declaration = CodeScope::getDefinition(symbol);
if (declaration.op == Operator::CALL_INTRINSIC){
if (declaration.getValueString() == "copy"){
mode = MODE_COPY;
}
}
if (symbol.identifier.version != VERSION_NONE){
mode = MODE_COPY;
if (symbol.identifier.version > 0){
Symbol versionPrev = Symbol{ScopedSymbol{symbol.identifier.id, symbol.identifier.version-1}, symbol.scope};
__graph.defineEndOfLife(versionPrev, symbol);
}
}
PassContext context2 = context.updateScope(symbol.scope);
std::list<Symbol> dependencies = process(declaration, context2, hintSymbol);
switch (mode) {
case MODE_COPY: __graph.applyDependentEndOfLife(SymbolOrPlaceholder{SYMBOL, symbol}, dependencies); break;
case MODE_ALIAS: __graph.applyDependentEndOfLife(__graph.getEndOfLife(symbol), dependencies); break;
}
__graph.applyNatualDependencies(symbol, dependencies);
__symbolsVisited.put(symbol, true);
return list<Symbol>{symbol};
}
VersionsGraph&
VersionsPass::getResultGraph(){
return __graph;
}
void
VersionsPass::finish(){
assert(__graph.validate() && "Can't validate versions graph");
Attachments::init<VersionImposedDependency>(__graph.representAsAttachments());
}
}} //end of namespace xreate::versions
diff --git a/cpp/src/query/containers.cpp b/cpp/src/query/containers.cpp
index 023551e..b08c36b 100644
--- a/cpp/src/query/containers.cpp
+++ b/cpp/src/query/containers.cpp
@@ -1,178 +1,178 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
*
* containers.cpp
* Created on 3/14/15.
*/
/**
* \file query/containers.h
* \brief Represents reasoner's solution on [Container implementations](/w/concepts/containers)
*/
-#include <clasplayer.h>
+#include <transcendlayer.h>
#include "query/containers.h"
using namespace std;
using namespace xreate::containers;
using namespace xreate;
Implementation
Query::queryImplementation(xreate::Symbol const &s) {
if (Attachments::exists<Implementation>(s))
{
return Attachments::get<Implementation>(s);
}
return Implementation::create(s);
}
Query::Query(){
Attachments::init<Implementation>();
}
void
-Query::init(ClaspLayer* clasp)
+Query::init(TranscendLayer* transcend)
{
if (flagIsDataLoaded) return;
map<Symbol, Symbol> prototypes;
map<Symbol, string> roots;
//Read all proto data
- auto range = clasp->query(Config::get("containers.id.prototypes"));
+ auto range = transcend->query(Config::get("containers.id.prototypes"));
if (range.size())
for(auto atom: range) {
- auto data = ClaspLayer::parse<SymbolPacked, SymbolPacked>(atom.second);
- Symbol root = clasp->unpack(get<0> (data));
- Symbol prototype = clasp->unpack(get<1> (data));
+ auto data = TranscendLayer::parse<SymbolPacked, SymbolPacked>(atom.second);
+ Symbol root = transcend->unpack(get<0> (data));
+ Symbol prototype = transcend->unpack(get<1> (data));
prototypes[root] = prototype;
}
//Fill implementation data for a data sources:
- range = clasp->query(Config::get("containers.id.implementations"));
+ range = transcend->query(Config::get("containers.id.implementations"));
if (range.size())
for(auto atom: range)
{
- auto data = ClaspLayer::parse<SymbolPacked, string>(atom.second);
+ auto data = TranscendLayer::parse<SymbolPacked, string>(atom.second);
- Symbol var = clasp->unpack(get<0>(data));
+ Symbol var = transcend->unpack(get<0>(data));
string implSerialized = get<1>(data);
//data source, has no prototypes:
if (!prototypes.count(var))
{
Implementation impl = Implementation::create(var);
Attachments::put<Implementation>(var, move(impl));
continue;
}
roots.emplace(move(var), move(implSerialized));
}
//fill implementation data for a cluster roots
for (const pair<Symbol, string> & root: roots)
{
Symbol prototype = prototypes[root.first];
while (prototypes.count(prototype)) {
prototype = prototypes.at(prototype);
}
Attachments::put<Implementation>(root.first, Implementation(Attachments::get<Implementation>(prototype)));
}
// read cluster data and fill implementation data for cluster members
- range = clasp->query(Config::get("containers.id.clusters"));
+ range = transcend->query(Config::get("containers.id.clusters"));
if (range.size())
for(auto atom: range)
{
- auto info = ClaspLayer::parse<SymbolPacked, SymbolPacked>(atom.second);
+ auto info = TranscendLayer::parse<SymbolPacked, SymbolPacked>(atom.second);
- Symbol root = clasp->unpack(get<0>(info));
- Symbol child = clasp->unpack(get<1>(info));
+ Symbol root = transcend->unpack(get<0>(info));
+ Symbol child = transcend->unpack(get<1>(info));
if (!(child == root) && (Attachments::exists<Implementation>(root))) {
Implementation rootImpl = Attachments::get<Implementation>(root);
Attachments::put<Implementation>(child, move(rootImpl));
}
}
flagIsDataLoaded = true;
}
//static ImplementationData* create(Symbol var, std::string implSerialized, const ImplementationData* implPrototype);
Implementation
Implementation::create(const Symbol &var)
{
//TODO review implementation determination strategy
Expression varDecl = CodeScope::getDefinition(var);
switch (varDecl.op)
{
case Operator::LIST_RANGE: {
ImplementationRec<ON_THE_FLY> rec{var};
return {ON_THE_FLY, rec};
}
case Operator::LIST: {
return {SOLID, ImplementationRec<SOLID> {varDecl.getOperands().size()}};
}
default: break;
};
ImplementationLinkedList ill(var);
if (ill){
return ill.getImplementationData();
}
assert(false && "Unable to determine proper implementation for the symbol");
return Implementation();
}
Implementation
Implementation::create(const Symbol& var, const std::string& implSerialized)
{
Expression varDecl = CodeScope::getDefinition(var);
if (implSerialized == Config::get("containers.impl.solid"))
{
return {SOLID, ImplementationRec<SOLID>{varDecl.operands.size()}};
} else if (implSerialized == Config::get("containers.impl.onthefly")) {
return {ON_THE_FLY, ImplementationRec<ON_THE_FLY>{var}};
}
assert(false && "unable to determine proper implementation for the symbol");
return Implementation();
}
ImplementationLinkedList::ImplementationLinkedList(const Symbol& source)
: flagIsValid(false), s(source){
const Expression& sourceExpr = CodeScope::getDefinition(source);
if (sourceExpr.tags.count(Config::get("containers.id.linkedlist"))){
flagIsValid = true;
Expression tagLinkedlist = sourceExpr.tags.at(Config::get("containers.id.linkedlist"));
assert(tagLinkedlist.operands.size() == 2);
fieldPointer = tagLinkedlist.operands.at(0).getValueString();
terminator = tagLinkedlist.operands.at(1);
}
}
ImplementationLinkedList:: operator bool () const{
return flagIsValid;
}
Implementation
ImplementationLinkedList::getImplementationData() const {
return {ON_THE_FLY, ImplementationRec<ON_THE_FLY>{s}};
}
diff --git a/cpp/src/query/containers.h b/cpp/src/query/containers.h
index 16873b4..8a814f3 100644
--- a/cpp/src/query/containers.h
+++ b/cpp/src/query/containers.h
@@ -1,93 +1,93 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
*
* containers.h
* Created on 3/14/15.
*/
#ifndef _XREATE_CONTAINERSQUERY_H_
#define _XREATE_CONTAINERSQUERY_H_
#include "xreatemanager.h"
-#include "clasplayer.h"
+#include "transcendlayer.h"
#include <boost/variant.hpp>
namespace xreate {
namespace containers {
enum ImplementationType {SOLID, ON_THE_FLY, LINKED_LIST};
template<ImplementationType I>
struct ImplementationRec;
template<>
struct ImplementationRec<SOLID> {
size_t size;
};
template<>
struct ImplementationRec<ON_THE_FLY>{
Symbol source;
};
struct Implementation;
struct ImplementationLinkedList {
bool flagIsValid;
std::string fieldPointer;
Expression terminator;
ImplementationLinkedList(const Symbol& source);
operator bool() const;
Implementation getImplementationData() const;
private:
Symbol s;
};
struct Implementation {
typedef boost::variant<ImplementationRec<SOLID>, ImplementationRec<ON_THE_FLY>> Variant;
ImplementationType impl;
Variant data;
static Implementation create(const Symbol &var);
static Implementation create(const Symbol& var, const std::string &implSerialized);
static Implementation create(const Symbol& var, const Implementation& proto);
template<ImplementationType I>
const ImplementationRec<I>& extract() const{
const ImplementationRec<I>& rec = boost::get<ImplementationRec<I>>(data);
return rec;
}
};
/** \brief Extracts solution about container implementation
* \sa xreate::containers::Iterator
*/
class Query : public xreate::IQuery {
public:
static Implementation queryImplementation(xreate::Symbol const &s);
- void init(ClaspLayer* clasp);
+ void init(TranscendLayer* transcend);
Query();
~Query(){}
private:
bool flagIsDataLoaded = false;
PassManager *man;
};
}
template<>
struct AttachmentsDict<containers::Implementation> {
typedef containers::Implementation Data;
static const unsigned int key = 1;
};
}
#endif //_XREATE_CONTAINERSQUERY_H_
diff --git a/cpp/src/query/polymorph.cpp b/cpp/src/query/polymorph.cpp
index d3e15db..ca9bc4c 100644
--- a/cpp/src/query/polymorph.cpp
+++ b/cpp/src/query/polymorph.cpp
@@ -1,55 +1,55 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: polymorph.cpp
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on November 9, 2017, 12:14 PM
*/
#include "polymorph.h"
using namespace std;
namespace xreate { namespace polymorph {
const std::string atomPolymorph = "dfa_callguard";
void
-PolymorphQuery::init(ClaspLayer* clasp){
- __clasp = clasp;
+PolymorphQuery::init(TranscendLayer* transcend){
+ __transcend = transcend;
- StaticModel queryResult = clasp->query(atomPolymorph);
+ StaticModel queryResult = transcend->query(atomPolymorph);
if (queryResult.size()){
for (auto entry: queryResult){
- auto answer = ClaspLayer::parse<SymbolNode, Expression>(entry.second);
+ auto answer = TranscendLayer::parse<SymbolNode, Expression>(entry.second);
SymbolNode symbCaller = std::get<0>(answer);
- SymbolGeneralized symbCallerUnpacked = clasp->unpack(symbCaller);
+ SymbolGeneralized symbCallerUnpacked = transcend->unpack(symbCaller);
Expression guard = std::get<1>(answer);
__cacheEarlyReasoning.emplace(symbCallerUnpacked, guard);
}
}
}
Expression
PolymorphQuery::get(const Expression& e){
SymbolGeneralized symbol=Attachments::exists<SymbolAlias>(e)?
SymbolGeneralized(Attachments::get<SymbolAlias>(e))
: SymbolGeneralized(SymbolAnonymous{e.id});
if (__cacheEarlyReasoning.count(symbol)){
return __cacheEarlyReasoning.at(symbol);
}
- SymbolNode symbolPacked = __clasp->pack(symbol, "");
- StaticModel answer = __clasp->queryCompiled().queryLate(atomPolymorph, symbolPacked);
+ SymbolNode symbolPacked = __transcend->pack(symbol, "");
+ StaticModel answer = __transcend->queryCompiled().queryLate(atomPolymorph, symbolPacked);
assert(answer.size() && "Can't find a guard");
Expression result;
- tie(result) = ClaspLayer::parse<Expression>(answer.begin()->second);
+ tie(result) = TranscendLayer::parse<Expression>(answer.begin()->second);
return result;
}
}} //end of xreate::polymorph
diff --git a/cpp/src/query/polymorph.h b/cpp/src/query/polymorph.h
index d3374c5..3b28263 100644
--- a/cpp/src/query/polymorph.h
+++ b/cpp/src/query/polymorph.h
@@ -1,32 +1,32 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: polymorph.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on November 9, 2017, 12:14 PM
*/
#ifndef POLYMORPHQUERY_H
#define POLYMORPHQUERY_H
-#include "clasplayer.h"
+#include "transcendlayer.h"
#include <unordered_map>
namespace xreate { namespace polymorph {
class PolymorphQuery: public IQuery {
public:
- virtual void init(ClaspLayer* clasp) override;
+ virtual void init(TranscendLayer* transcend) override;
Expression get(const Expression& e);
private:
std::unordered_map<SymbolGeneralized, Expression> __cacheEarlyReasoning;
- ClaspLayer* __clasp = nullptr;
+ TranscendLayer* __transcend = nullptr;
};
}}//end of xreate::polymorph
#endif /* POLYMORPHQUERY_H */
diff --git a/cpp/src/clasplayer.cpp b/cpp/src/transcendlayer.cpp
similarity index 85%
rename from cpp/src/clasplayer.cpp
rename to cpp/src/transcendlayer.cpp
index d3d2980..2d86470 100644
--- a/cpp/src/clasplayer.cpp
+++ b/cpp/src/transcendlayer.cpp
@@ -1,560 +1,560 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
- * File: clasplayer.cpp
+ * File: transcendlayer.cpp
*/
/**
- * \file clasplayer.h
- * \brief Resoner. Wrapper over Clasp reasoner library
+ * \file transcendlayer.h
+ * \brief Resoner. Wrapper over the external Clasp reasoner library
*/
-#include "clasplayer.h"
+#include "transcendlayer.h"
#include "analysis/utils.h"
#include "utils.h"
#include <gringo/scripts.hh>
#include <boost/format.hpp>
#include <boost/algorithm/string/join.hpp>
#include <iostream>
#include <memory>
#include <boost/variant/detail/apply_visitor_binary.hpp>
using namespace std;
//TODO escape identifiers started with upper case symbol
namespace xreate {
bool operator==(const SymbolAnonymous& s1, const SymbolAnonymous& s2){
return s1.id == s2.id && s1.flagIsUsed == s2.flagIsUsed;
}
struct VisitorSymbolNodeHash : public boost::static_visitor<size_t> {
std::size_t operator()(const xreate::SymbolPacked& node) const noexcept{
return 2* (node.identifier + 3 * node.scope + 5 * std::abs(node.version));
}
std::size_t operator()(const xreate::SymbolAnonymous& node) const noexcept{
return 7 * node.id;
}
};
}
namespace std {
std::size_t
hash<xreate::SymbolNode>::operator()(xreate::SymbolNode const& s) const noexcept {
return boost::apply_visitor(xreate::VisitorSymbolNodeHash(), s);
}
std::size_t
hash<xreate::SymbolGeneralized>::operator()(xreate::SymbolGeneralized const& s) const noexcept {
return xreate::AttachmentsId<xreate::SymbolGeneralized>::getId(s);
}
}
namespace xreate {
void
-ClaspLayer::printWarnings(std::ostream& out) {
+TranscendLayer::printWarnings(std::ostream& out) {
const std::string warningTag = "warning";
auto warningsModel = query(warningTag);
if(warningsModel.size())
for (auto warning: warningsModel) {
unsigned int warningId;
Gringo::Symbol params;
std::tie(warningId, params) = parse<unsigned int, Gringo::Symbol>(warning.second);
cout << "Warning: " << __warnings.at(warningId) << " ";
params.print(out);
out<<params;
}
}
bool
-ClaspLayer::handleSolution(Gringo::Model const &model) {
+TranscendLayer::handleSolution(Gringo::Model const &model) {
cout << "Model: " << endl;
- const string& atomBindVar = Config::get("clasp.bindings.variable");
- const string& atomBindFunc = Config::get("clasp.bindings.function");
- const string& atomBindScope = Config::get("clasp.bindings.scope");
+ const string& atomBindVar = Config::get("transcend.bindings.variable");
+ const string& atomBindFunc = Config::get("transcend.bindings.function");
+ const string& atomBindScope = Config::get("transcend.bindings.scope");
const string& atomLateStatement = "late";
for (Gringo::Symbol atom : model.atoms(clingo_show_type_atoms)) {
atom.print(cout);
cout <<" | "<< endl;
string atomName(atom.name().c_str());
if (atomName == atomBindVar || atomName == atomBindFunc || atomName == atomBindScope){
string atomAlias = std::get<1>(parse<Gringo::Symbol, Gringo::Symbol>(atom)).name().c_str();
__model.addStaticAtom(atomAlias, atom);
} else if(atomName == atomLateStatement){
//late atom format: (Symbol, (tuple of keys), (tuple of values), late-annotation)
auto atomLate = parse<SymbolPacked, std::list<SymbolPacked>, std::list<Expression>, Gringo::Symbol>(atom);
const string& atomAlias = get<3>(atomLate).name().c_str();
__model.addLateAtom(atomAlias, get<0>(atomLate),
get<3>(atomLate), get<1>(atomLate),
get<2>(atomLate));
}
__model.addStaticAtom(atomName, atom);
}
return true;
}
void
-ClaspLayer::registerReport(IAnalysisReport* report){
+TranscendLayer::registerReport(IAnalysisReport* report){
__reports.push_back(report);
}
void
-ClaspLayer::runReports(){
+TranscendLayer::runReports(){
for(IAnalysisReport* report: __reports){
report->print(__partGeneral);
delete report;
}
__reports.clear();
}
void
-ClaspLayer::addRuleWarning(const RuleWarning &rule) {
+TranscendLayer::addRuleWarning(const RuleWarning &rule) {
//__partGeneral << rule << endl;
list<string> domains;
boost::format formatDef("%1%(%2%)");
std::transform(rule.__args.begin(), rule.__args.end(), std::inserter(domains, domains.begin()),
[&formatDef](const std::pair<std::string, DomainAnnotation> &argument) {
string domain;
switch (argument.second) {
case DomainAnnotation::FUNCTION:
domain = "function";
break;
case DomainAnnotation::VARIABLE:
domain = "variable";
break;
}
return boost::str(formatDef % domain % argument.first);
});
list<string> vars;
std::transform(rule.__args.begin(), rule.__args.end(), std::inserter(vars, vars.begin()),
[](const std::pair<std::string, DomainAnnotation> &argument) {
return argument.first.c_str();
});
list<list<string>> guardsRaw;
std::transform(rule.__guards.begin(), rule.__guards.end(), std::inserter(guardsRaw, guardsRaw.begin()),
[this](const Expression &guard) {
return xreate::analysis::compile(guard);
});
const list<string>& guards = xreate::analysis::multiplyLists(std::move(guardsRaw));
list<string> &&branches = xreate::analysis::compileNeg(rule.__condition);
boost::format formatWarning("warning(%1%, (%2%)):- %3%, %4%, %5%.");
for (const string &guardsJoined: guards)
for (const string &branch: branches) {
unsigned int hook = registerWarning(string(rule.__message));
__partGeneral << formatWarning
%(hook)
%(boost::algorithm::join(vars, ", "))
%(branch)
%(guardsJoined)
%(boost::algorithm::join(domains, ", "))
<<endl;
}
}
unsigned int
-ClaspLayer::registerWarning(std::string &&message) {
+TranscendLayer::registerWarning(std::string &&message) {
static int warningId = 0;
__warnings.emplace(warningId, message);
return warningId++;;
}
void
-ClaspLayer::involveImports() {
+TranscendLayer::involveImports() {
ostream &out = __partGeneral;
if(ast)
for (string fn: ast->__rawImports)
{
std::ifstream file(fn);
if (!file){
std::cout << "Can't process script file: " << fn << std::endl;
assert(false);
}
while(!file.eof()){
string line;
std::getline(file, line);
out << line << endl;
}
}
}
void
-ClaspLayer::addRawScript(std::string&& script){
+TranscendLayer::addRawScript(std::string&& script){
__partGeneral << script;
}
void
-ClaspLayer::run() {
+TranscendLayer::run() {
involveImports();
runReports();
ostringstream program;
program << __partTags.str() << __partGeneral.str();
cout << FYEL(program.str()) << endl;
std::vector<char const *> args{"clingo", nullptr};
DefaultGringoModule moduleDefault;
Gringo::Scripts scriptsDefault(moduleDefault);
ClingoLib ctl(scriptsDefault, 0, args.data(), {}, 0);
ctl.add("base", {}, program.str());
ctl.ground({{"base", {}}}, nullptr);
// solve
Gringo::SolveResult result = ctl.solve([this](Gringo::Model const &model) {
this->handleSolution(model);
return true;
}, {});
if (result.satisfiable() == Gringo::SolveResult::Satisfiable) {
cout << FGRN("SUCCESSFULLY") << endl;
} else {
cout << FRED("UNSUCCESSFULLY") << endl;
}
-// invoke all query plugins to process clasp data
+// invoke all query plugins to process solution
for (auto q: __queries)
{
q.second->init(this);
}
}
-ClaspLayer::ClaspLayer(): __model(this), ast(nullptr){
+TranscendLayer::TranscendLayer(): __model(this), ast(nullptr){
}
const ReasoningModel&
-ClaspLayer::queryCompiled() {
+TranscendLayer::queryCompiled() {
return __model;
}
StaticModel
-ClaspLayer::query(const std::string& atom){
+TranscendLayer::query(const std::string& atom){
return __model.queryStatic(atom);
}
ScopePacked
-ClaspLayer::pack(const CodeScope* const scope) {
+TranscendLayer::pack(const CodeScope* const scope) {
auto pos = __indexScopes.emplace(scope, __indexScopes.size());
if (pos.second)
__registryScopes.push_back(scope);
return pos.first->second;
}
size_t
-ClaspLayer::getScopesCount() const{
+TranscendLayer::getScopesCount() const{
return __registryScopes.size();
}
SymbolPacked
-ClaspLayer::pack(const Symbol& symbol, std::string hintSymbolName)
+TranscendLayer::pack(const Symbol& symbol, std::string hintSymbolName)
{
SymbolPacked result(symbol.identifier.id, symbol.identifier.version, pack(symbol.scope));
__indexSymbolNameHints.emplace(result, hintSymbolName);
return result;
}
Symbol
-ClaspLayer::unpack(const SymbolPacked& symbol)
+TranscendLayer::unpack(const SymbolPacked& symbol)
{
return Symbol{ScopedSymbol{symbol.identifier, symbol.version}, __registryScopes[symbol.scope]};
};
std::string
-ClaspLayer::getHintForPackedSymbol(const SymbolPacked& symbol){
+TranscendLayer::getHintForPackedSymbol(const SymbolPacked& symbol){
auto result = __indexSymbolNameHints.find(symbol);
return (result == __indexSymbolNameHints.end())? "" : result->second;
}
IQuery*
-ClaspLayer::registerQuery(IQuery *query, const QueryId& id) {
+TranscendLayer::registerQuery(IQuery *query, const QueryId& id) {
return __queries.emplace(id, query).first->second;
}
IQuery*
-ClaspLayer::getQuery(const QueryId& id){
+TranscendLayer::getQuery(const QueryId& id){
assert(__queries.count(id) && "Undefined query");
return __queries.at(id);
}
class VisitorUnpackSymbol: public boost::static_visitor<SymbolGeneralized> {
public:
- VisitorUnpackSymbol(ClaspLayer* clasp): __clasp(clasp) {}
+ VisitorUnpackSymbol(TranscendLayer* transcend): __transcend(transcend) {}
SymbolGeneralized operator()(const SymbolPacked& symbol) const {
- return __clasp->unpack(symbol);
+ return __transcend->unpack(symbol);
}
SymbolGeneralized operator()(const SymbolAnonymous& symbol) const {
return symbol;
}
private:
- ClaspLayer* __clasp;
+ TranscendLayer* __transcend;
};
class VisitorPackSymbol: public boost::static_visitor<SymbolNode> {
public:
- VisitorPackSymbol(ClaspLayer* clasp, const std::string& hintSymbolName)
- : __clasp(clasp), __hint(hintSymbolName) {}
+ VisitorPackSymbol(TranscendLayer* transcend, const std::string& hintSymbolName)
+ : __transcend(transcend), __hint(hintSymbolName) {}
SymbolNode operator()(const Symbol& symbol) const {
- return __clasp->pack(symbol, __hint);
+ return __transcend->pack(symbol, __hint);
}
SymbolNode operator()(const SymbolAnonymous& symbol) const {
return symbol;
}
private:
- ClaspLayer* __clasp;
+ TranscendLayer* __transcend;
std::string __hint;
};
-SymbolNode ClaspLayer::pack(const SymbolGeneralized& symbol, const std::string& hintSymbolName){
+SymbolNode TranscendLayer::pack(const SymbolGeneralized& symbol, const std::string& hintSymbolName){
return boost::apply_visitor(VisitorPackSymbol(this, hintSymbolName), symbol);
}
-SymbolGeneralized ClaspLayer::unpack(const SymbolNode& symbol)
+SymbolGeneralized TranscendLayer::unpack(const SymbolNode& symbol)
{
return boost::apply_visitor(VisitorUnpackSymbol(this), symbol);
}
boost::optional<Gringo::Symbol>
GuardedAnnotation::get(const std::list<Expression>& keys) const{
for (const auto& entry: guardedSymbols){
const std::list<Expression>& keysExpected = entry.first;
auto keysIt = keys.begin();
bool result = true;
for(const Expression& keyExpected: keysExpected){
if(! (keyExpected == *keysIt)) {result = false; break; }
++keysIt;
}
if(!result) continue;
return entry.second;
}
return boost::none;
}
std::list<Expression>
ReasoningModel::findKeys(const std::list<SymbolPacked>& keys) const{
std::list<Expression> result;
std::transform(keys.begin(), keys.end(), std::inserter(result, result.end()), [this](const SymbolPacked& key){
- return Attachments::get<LateBinding>(this->clasp->unpack(key));
+ return Attachments::get<LateBinding>(this->transcend->unpack(key));
});
return result;
}
void ReasoningModel::addStaticAtom(const std::string& atomAlias, const Gringo::Symbol& atom){
modelStatic.emplace(atomAlias, atom);
}
void ReasoningModel::addLateAtom(const std::string& alias, const SymbolNode& symbol,
const Gringo::Symbol& atom, const std::list<SymbolPacked>& guardKeys,
const std::list<Expression>& guardBindings){
LateModel& model = modelGuarded[alias];
if(!model.bindings.count(symbol)){
model.bindings.emplace(symbol, guardKeys);
}
GuardedAnnotation& annotation = model.annotations[symbol];
annotation.guardedSymbols.push_back(make_pair(guardBindings, atom));
}
StaticModel
ReasoningModel::queryStatic(const std::string& alias) const{
StaticModel result;
if (! modelStatic.count(alias)){
return result;
}
auto currentDataRange = modelStatic.equal_range(alias);
std::copy(currentDataRange.first, currentDataRange.second, std::inserter(result, result.end()));
return result;
}
StaticModel
ReasoningModel::queryLate(const std::string& alias, const SymbolNode& symbol) const{
StaticModel result;
if (!modelGuarded.count(alias)) return StaticModel();
const LateModel& model = modelGuarded.at(alias);
assert(model.bindings.count(symbol));
const list<SymbolPacked>& bindings = model.bindings.at(symbol);
list<Expression>&& keys = findKeys(bindings);
const GuardedAnnotation& annGuarded = model.annotations.at(symbol);
auto ann = annGuarded.get(keys);
if(ann){
result.emplace(make_pair(alias, *ann));
}
return result;
}
bool operator==(const SymbolPacked& s1, const SymbolPacked& s2)
{
return s1.identifier == s2.identifier && s1.scope == s2.scope;
}
bool operator<(const SymbolPacked& s1, const SymbolPacked& s2)
{
return s1.scope < s2.scope || (s1.scope == s2.scope && s1.identifier < s2.identifier);
}
Expression
ParseImplAtom<Expression>::get(const Gringo::Symbol& atom) {
switch (atom.type()) {
case Gringo::SymbolType::Num: return Expression(atom.num());
case Gringo::SymbolType::Str: return Expression(Atom<String_t>(std::string(atom.string().c_str())));
case Gringo::SymbolType::Fun:
{
//FUNC
Expression result(Operator::CALL,{Expression(Atom<Identifier_t>(std::string(atom.name().c_str())))});
for (const Gringo::Symbol& arg : atom.args()) {
result.addArg(ParseImplAtom<Expression>::get(arg));
}
return result;
}
default:
{
assert(false);
}
}
}
int
ParseImplAtom<int>::get(const Gringo::Symbol& atom) {
switch (atom.type()){
case Gringo::SymbolType::Num: return atom.num();
default: break;
}
assert(false && "Inappropriate symbol type");
}
std::string
ParseImplAtom<std::string>::get(const Gringo::Symbol& atom) {
switch (atom.type()) {
case Gringo::SymbolType::Str: return atom.string().c_str();
case Gringo::SymbolType::Fun: return atom.name().c_str();
default: break;
}
assert(false && "Inappropriate symbol type");
}
SymbolPacked
ParseImplAtom<SymbolPacked>::get(const Gringo::Symbol& atom) {
- auto result = ClaspLayer::parse<int, int, int>(atom);
+ auto result = TranscendLayer::parse<int, int, int>(atom);
return SymbolPacked(std::get<0>(result), std::get<1>(result), std::get<2>(result));
};
Gringo::Symbol
ParseImplAtom<Gringo::Symbol>::get(const Gringo::Symbol& atom) {
return atom;
}
SymbolNode
ParseImplAtom<SymbolNode>::get(const Gringo::Symbol& atom) {
assert(atom.type() == Gringo::SymbolType::Fun
&& "Inappropriate symbol type");
if (atom.name() == "a"){
- return SymbolAnonymous{(unsigned int) std::get<0>(ClaspLayer::parse<int>(atom))};
+ return SymbolAnonymous{(unsigned int) std::get<0>(TranscendLayer::parse<int>(atom))};
} else if (atom.name() == "s"){
return ParseImplAtom<SymbolPacked>::get(atom);
}
assert(false && "Wrong symbol format");
}
class VisitorSymbolId: public boost::static_visitor<unsigned int> {
public:
unsigned int operator()(const Symbol& symbol) const {
return AttachmentsId<Symbol>::getId(symbol);
}
unsigned int operator()(const SymbolAnonymous& symbol) const {
return symbol.id;
}
};
unsigned int
AttachmentsId<SymbolGeneralized>::getId(const SymbolGeneralized& symbol){
return boost::apply_visitor(VisitorSymbolId(), symbol);
}
} //end of xreate namespace
/**
- * \class xreate::ClaspLayer
+ * \class xreate::TranscendLayer
* \brief Reasoning and logic Solver.
*
* Wraps external brilliant fantastic tool [Clasp solver](https://potassco.org/clasp/)
*
- * For building *logic program* for reasoning ClaspLayer takes input from:
+ * For building *logic program* for reasoning TranscendLayer takes input from:
* - Raw scripts. Client could append arbitrary ASP script to _logic program_. \ref addRawScript()
* - Includes. There is possibility to specify external files with ASP scripts
* to append to _logic program_. \ref involveImports() (private member)
* - Diagnostic rules. Rules that produce diagnostic messages during
* compilation(warnings) or even able to halt compilation with errors.
* addRuleWarning(), \ref registerWarning()
* - DFA data. \ref setDFAData()
* - CFA data. \ref setCFAData()
* - Dominators Analysis. See xreate::dominators::DominatorsTreeAnalysisProvider.
* Executed by \ref run()
* - Context rules. See xreate::ContextRule and general [Context Explanation](/w/concepts/context)
*
* Data sources implement xreate::IAnalysisReport. Generally, input could be loosely divided into three categories:
* - *Internally derived* data. CFA, DFA, Dominators analyses *automatically* feed reasoner by
* useful insights about data, structure and algorithms of a program
* - *User provided* data. CFA, DFA, Diagnostic/Context rules feed reasoner by
* annotations Developer specifically provides manually
* - *External* data. Raw scripts and includes feed reasoner with third-party data
* related to a different aspects of a program possibly produced by external analyzers
*
- * Once ClaspLayer got input from all providers and logic program is fully constructed
- * it runs external Clasp solver and receives back desired solutions.
+ * Once TranscendLayer got input from all providers and logic program is fully constructed
+ * it runs external Clasp reasoner and receives back desired solutions.
*
- * Output of Clasp reasoner is recognized and accessed via *queries*.
+ * Output of the external Clasp reasoner is recognized and accessed via *queries*.
* IQuery represents an interface between reasoner's output and rest of Xreate.
* Each query inherits xreate::IQuery interface. Currently there are queries as follows:
* - xreate::containers::Query to catch solutions regarding Containers implementation. See [Containers Explanation](/w/concepts/containers)
* - xreate::context::ContextQuery to catch solution regarding Context. See [Context Explanation](/w/concepts/context)
*
* \sa See xreate::dfa::DFAPass, xreate::cfa::CFAPass, xreate::IQuery, xreate::IAnalysisReport, xreate::dominators::DominatorsTreeAnalysisProvider
- */
\ No newline at end of file
+ */
diff --git a/cpp/src/clasplayer.h b/cpp/src/transcendlayer.h
similarity index 95%
rename from cpp/src/clasplayer.h
rename to cpp/src/transcendlayer.h
index 2328067..5f20f89 100644
--- a/cpp/src/clasplayer.h
+++ b/cpp/src/transcendlayer.h
@@ -1,314 +1,316 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
- * File: clasplayer.h
+ * File: transcendlayer.h
*/
-#ifndef CLASPLAYER_H
-#define CLASPLAYER_H
+#ifndef transcendLAYER_H
+#define transcendLAYER_H
#include "ast.h"
#include "contextrule.h"
#include <clingo/clingocontrol.hh>
#include <string>
#include <climits>
#include <unordered_map>
#include <boost/bimap.hpp>
#include <boost/bimap/multiset_of.hpp>
#include <boost/optional.hpp>
#include <boost/scoped_ptr.hpp>
#include <list>
#include <limits>
namespace xreate {
typedef unsigned int ScopePacked;
const ScopePacked SCOPE_ABSTRACT_GLOBAL = std::numeric_limits<ScopePacked>::max();
struct SymbolPacked {
SymbolPacked(){}
SymbolPacked(ScopedSymbol i, ScopePacked s): identifier(i.id), version(i.version), scope(s){}
SymbolPacked(VNameId symbolId, versions::VariableVersion symbolVersion, ScopePacked symbolScope)
: identifier(symbolId), version(symbolVersion), scope(symbolScope){}
VNameId identifier;
versions::VariableVersion version;
ScopePacked scope;
};
bool operator==(const SymbolPacked& s1, const SymbolPacked& s2);
bool operator<(const SymbolPacked& s1, const SymbolPacked& s2);
struct SymbolAnonymous {
unsigned int id;
bool flagIsUsed = false;
};
bool operator==(const SymbolAnonymous& s1, const SymbolAnonymous& s2);
typedef boost::variant<SymbolAnonymous, SymbolPacked> SymbolNode;
+
+//DEBT use SymbolGeneralized communicating with Analysis rather than Symbol
typedef boost::variant<SymbolAnonymous, Symbol> SymbolGeneralized;
template<>
struct AttachmentsId<SymbolGeneralized>{
static unsigned int getId(const SymbolGeneralized& symbol);
};
} namespace std {
template<>
struct hash<xreate::SymbolNode> {
std::size_t operator()(xreate::SymbolNode const& s) const noexcept;
};
template<>
struct hash<xreate::SymbolGeneralized> {
std::size_t operator()(xreate::SymbolGeneralized const& s) const noexcept;
};
}
namespace xreate {
enum class DFGConnection {
STRONG, WEAK, PROTOTYPE
};
/** \brief Designated to mark analysis results that can be composed as *logic program* */
class IAnalysisReport {
public:
/** \brief Composes *logic program* based on analysis data into ASP format and appends to a stream*/
virtual void print(std::ostringstream& output) const = 0;
virtual ~IAnalysisReport(){};
};
/** \brief Logic program query interface */
class IQuery {
public:
- virtual void init(ClaspLayer* clasp) = 0;
+ virtual void init(TranscendLayer* transcend) = 0;
virtual ~IQuery() {}
};
enum class QueryId {
ContainersQuery,
PolymorphQuery
};
namespace dfa{
class DFAGraph;
}
namespace cfa {
class CFAGraph;
}
typedef std::multimap<std::string, Gringo::Symbol> StaticModel;
typedef StaticModel::const_iterator StaticModelIterator;
struct GuardedAnnotation{
std::list<std::pair<std::list<Expression>, Gringo::Symbol>> guardedSymbols;
boost::optional<Gringo::Symbol> get(const std::list<Expression>& keys) const;
};
struct LateModel{
std::unordered_map<SymbolNode, GuardedAnnotation> annotations;
std::unordered_map<SymbolNode, std::list<SymbolPacked>> bindings;
};
//DEBT implement querying as a view/joining iterators without actual data copying
//DEBT how to implement late model RESET(invalidate all child models)
class ReasoningModel{
public:
- ReasoningModel(ClaspLayer* claspLayer): clasp(claspLayer) {}
+ ReasoningModel(TranscendLayer* transcendLayer): transcend(transcendLayer) {}
void addLateAtom(const std::string& alias, const SymbolNode& symbol,
const Gringo::Symbol& atom, const std::list<SymbolPacked>& guardKeys,
const std::list<Expression>& guardBindings);
void addStaticAtom(const std::string& atomAlias, const Gringo::Symbol& atom);
StaticModel queryStatic(const std::string& atom) const;
StaticModel queryLate(const std::string& alias, const SymbolNode& symbol) const;
private:
- ClaspLayer* clasp;
+ TranscendLayer* transcend;
StaticModel modelStatic;
std::map<std::string, LateModel> modelGuarded;
std::list<Expression> findKeys(const std::list<SymbolPacked>& keys) const;
};
struct LateBinding;
template<>
struct AttachmentsDict<LateBinding>{
typedef Expression Data;
static const unsigned int key = 12;
};
-class ClaspLayer {
+class TranscendLayer {
friend class ContextRule;
/**\name Data Providers Management */
///@{
public:
void registerReport(IAnalysisReport* report);
void runReports();
/** \brief Appends arbitrary string to *logic program*
*/
void addRawScript(std::string&& script);
private:
std::list<IAnalysisReport*> __reports;
/** Includes external text files to a *logic program* */
void involveImports();
///@}
/**\name Queries Management */
///@{
public:
/** \brief Adds query. See xreate::IQuery */
IQuery* registerQuery(IQuery* query, const QueryId& id);
/** \brief Returns particular query. See xreate::IQuery */
IQuery* getQuery(const QueryId& id);
template<class ...Types>
static std::tuple<Types...> parse(const Gringo::Symbol& atom);
StaticModel query(const std::string& atom);
const ReasoningModel& queryCompiled();
size_t getScopesCount() const;
SymbolPacked pack(const Symbol& symbol, std::string hintSymbolName = "");
ScopePacked pack(const CodeScope * const scope);
Symbol unpack(const SymbolPacked& symbol);
SymbolNode pack(const SymbolGeneralized& symbol, const std::string& hintSymbolName);
SymbolGeneralized unpack(const SymbolNode& symbol);
std::string getHintForPackedSymbol(const SymbolPacked& symbol);
///@}
private:
std::map<QueryId, IQuery*> __queries;
ReasoningModel __model;
std::map<SymbolPacked, std::string> __indexSymbolNameHints;
std::unordered_map<const CodeScope*, unsigned int> __indexScopes;
std::vector<const CodeScope*> __registryScopes;
/**\name Diagnostic */
///@{
//TODO diagnostic move over to separate provider/query
public:
/** \brief Adds diagnostic rule */
void addRuleWarning(const RuleWarning &rule);
/** \brief Registers diagnostic messages */
unsigned int registerWarning(std::string &&message);
private:
std::map<unsigned int, std::string> __warnings;
void printWarnings(std::ostream& out);
///@}
///@{
public:
- ClaspLayer();
+ TranscendLayer();
/** \brief Executes reasoning */
void run();
///@}
AST *ast;
private:
std::ostringstream __partTags;
std::ostringstream __partGeneral;
bool handleSolution(Gringo::Model const &model);
};
template<class typ>
struct ParseImplAtom {
static typ get(const Gringo::Symbol& atom) {
return atom.num();
}
};
template<>
struct ParseImplAtom<int> {
static int get(const Gringo::Symbol& atom);
};
template<>
struct ParseImplAtom<std::string> {
static std::string get(const Gringo::Symbol& atom);
};
template<>
struct ParseImplAtom<SymbolPacked> {
static SymbolPacked get(const Gringo::Symbol& atom);
};
template<>
struct ParseImplAtom<SymbolNode> {
static SymbolNode get(const Gringo::Symbol& atom);
};
template<>
struct ParseImplAtom<Gringo::Symbol> {
static Gringo::Symbol get(const Gringo::Symbol& atom);
};
template<class ItemType>
struct ParseImplAtom<std::list<ItemType>>{
static std::list<ItemType>
get(const Gringo::Symbol& atom){
assert (atom.type() == Gringo::SymbolType::Fun);
std::list<ItemType> result;
for (const Gringo::Symbol& arg: atom.args()) {
result.push_back(ParseImplAtom<ItemType>::get(arg));
}
return result;
}
};
template<>
struct ParseImplAtom<Expression> {
static Expression get(const Gringo::Symbol& atom);
};
template<class Tuple, size_t index>
struct Parse_Impl {
static void parse(Tuple& tup, Gringo::SymSpan::iterator arg) {
const size_t tupleSize = std::tuple_size<Tuple>::value;
typedef typename std::tuple_element < tupleSize - index, Tuple>::type ElType;
ElType& el = std::get < tupleSize - index > (tup);
Gringo::Symbol atom = *arg;
el = ParseImplAtom<ElType>::get(atom);
Parse_Impl<Tuple, index - 1 > ::parse(tup, ++arg);
}
};
template<class Tuple>
struct Parse_Impl<Tuple, 0> {
static void parse(Tuple& tup, Gringo::SymSpan::iterator arg) {
}
};
template<class ...Types>
std::tuple<Types...>
-ClaspLayer::parse(const Gringo::Symbol& atom) {
+TranscendLayer::parse(const Gringo::Symbol& atom) {
typedef std::tuple < Types...> Tuple;
Tuple tup;
Parse_Impl<Tuple, std::tuple_size<Tuple>::value>::parse(tup, atom.args().first);
return tup;
}
} //end of xreate namespace
#endif
diff --git a/cpp/src/xreatemanager.cpp b/cpp/src/xreatemanager.cpp
index 47fbf75..1b5cddf 100644
--- a/cpp/src/xreatemanager.cpp
+++ b/cpp/src/xreatemanager.cpp
@@ -1,157 +1,157 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* xreatemanager.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on July 3, 2017, 6:03 PM
*/
#include "xreatemanager.h"
#include "pass/abstractpass.h"
-#include "clasplayer.h"
+#include "transcendlayer.h"
#include "aux/xreatemanager-decorators.h"
#include "llvmlayer.h"
#include "main/Parser.h"
#include <assert.h>
#include <list>
namespace xreate {
void
PassManager::registerPass(IPass* pass, const PassId& id, IPass* parent)
{
__passes.emplace(id, pass);
__passDependencies.emplace(parent, pass);
}
IPass*
PassManager::getPassById(const PassId& id){
assert(__passes.count(id));
return __passes[id];
}
bool
PassManager::isPassRegistered(const PassId& id){
return __passes.count(id);
}
void
PassManager::executePasses(){
std::list<IPass*> passes{nullptr};
while (passes.size()){
IPass* parent = passes.front();
auto range = __passDependencies.equal_range(parent);
for (auto i=range.first; i!=range.second; ++i){
IPass* pass = i->second;
pass->run();
pass->finish();
passes.push_back(pass);
}
passes.pop_front();
}
}
void
PassManager::prepare(AST* ast){
root = ast;
- clasp = new ClaspLayer();
- clasp->ast = ast;
+ transcend = new TranscendLayer();
+ transcend->ast = ast;
llvm = new LLVMLayer(ast);
}
PassManager::~PassManager(){}
typedef XreateManagerDecoratorFull XreateManagerDecoratorDefault;
namespace details{ namespace tier2{
XreateManager*
XreateManager::prepare(std::string&& code){
auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
man->prepareCode(std::move(code));
return man;
}
XreateManager*
XreateManager::prepare(FILE* code){
auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
man->prepareCode(code);
return man;
}
}}
namespace details { namespace tier1 {
XreateManager*
XreateManager::prepare(std::string&& code){
auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
man->prepareCode(std::move(code));
return man;
}
XreateManager*
XreateManager::prepare(FILE* code){
auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
man->prepareCode(code);
return man;
}
}}
/**
* \class xreate::XreateManager
* \brief Entry point of Xreate API
*
* Manages whole Xreate's internal workflow. There are 4 distinctive stages covered by XreateManager:
* - initPasses() To init passes
* - executePasses() To execute passes
* - analyse() To run reasoner
* - run() To run compiler
*
* For adaptability manager comes with several *Frontends*:
* - xreate::details::tier2::XreateManager has all stages accessible by client for full control
* - xreate::details::tier1::XreateManager has only analyse() and run(), where analyse() combines execution of all previous stages
* - xreate::XreateManager has only run() to combine all stages for convenient use
*
* Moreover there are *Backends*:
* - xreate::XreateManagerDecoratorBase Simple backend intended for inheritance without much functionality
* - XreateManagerDecoratorFull Backend intended to initialize all builtin passes
*
* Thus, client's code could combine desired frontend and desired backend as see fit.
* Default xreate::XreateManager connects full backend to init all builtin passes
* to a simplest frontend with only run() available to execute all stages at once
*/
/**
*\brief Constructs XreateManager for a given code
*/
XreateManager*
XreateManager::prepare(std::string&& code) {
auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
man->prepareCode(std::move(code));
return man;
}
/**
*\brief Constructs XreateManager for a given script file
*/
XreateManager*
XreateManager::prepare(FILE* code){
auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
man->prepareCode(code);
return man;
}
}
diff --git a/cpp/src/xreatemanager.h b/cpp/src/xreatemanager.h
index d5fbf43..1dfdc80 100644
--- a/cpp/src/xreatemanager.h
+++ b/cpp/src/xreatemanager.h
@@ -1,141 +1,141 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* xreatemanager.h
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on July 3, 2017, 6:03 PM
*/
/**
* \file
* \brief Entry point of Xreate API.
*
*/
#ifndef PASSMANAGER_H
#define PASSMANAGER_H
#include <string>
#include <map>
//stdio external
struct _IO_FILE;
typedef struct _IO_FILE FILE;
namespace xreate { namespace grammar { namespace main {
class Scanner;
}}}
namespace xreate {
class IPass;
-class ClaspLayer;
+class TranscendLayer;
class LLVMLayer;
class AST;
enum class PassId {
CFGPass,
CompilePass,
DFGPass,
EnvironmentTestsPass,
LoggerPass,
RulesPass,
InterpretationPass,
VersionsPass
};
/**
* \class PassManager
* \brief Base class to control passes
*/
class PassManager{
public:
void prepare(AST* ast);
void registerPass(IPass* pass, const PassId& id, IPass* prerequisite=nullptr);
IPass* getPassById(const PassId& id);
bool isPassRegistered(const PassId& id);
void executePasses();
virtual ~PassManager();
- ClaspLayer* clasp;
+ TranscendLayer* transcend;
LLVMLayer* llvm;
AST* root;
private:
std::map<PassId, IPass*> __passes;
std::multimap<IPass*, IPass*> __passDependencies;
};
namespace details{ namespace tier2{
class XreateManager: public virtual PassManager{
public:
virtual ~XreateManager(){};
virtual void initPasses()=0;
// virtual void executePasses()=0;
virtual void analyse()=0;
virtual void* run()=0;
static XreateManager* prepare(std::string&& code);
static XreateManager* prepare(FILE* code);
};
template<class Decorator>
class XreateManagerImpl: public Decorator {
public:
};
}} //namespace details::tier2
namespace details{ namespace tier1{
class XreateManager: public virtual PassManager{
public:
virtual void analyse()=0;
virtual void* run()=0;
static XreateManager* prepare(std::string&& code);
static XreateManager* prepare(FILE* code);
};
template<class Decorator>
class XreateManagerImpl: public XreateManager, public details::tier2::XreateManagerImpl<Decorator> {
typedef details::tier2::XreateManagerImpl<Decorator> PARENT;
public:
void analyse(){
PARENT::initPasses();
PARENT::executePasses();
PARENT::analyse();
}
void* run(){
return PARENT::run();
}
};
}} //namespace details::tier1
class XreateManager: public virtual PassManager{
public:
virtual void* run()=0;
static XreateManager* prepare(std::string&& code);
static XreateManager* prepare(FILE* code);
};
template<class Decorator>
class XreateManagerImpl: public XreateManager, public details::tier1::XreateManagerImpl<Decorator>{
typedef details::tier1::XreateManagerImpl<Decorator> PARENT;
public:
void* run(){
PARENT::analyse();
return PARENT::run();
}
};
} //namespace xreate
#endif
diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt
index 9faa990..afac651 100644
--- a/cpp/tests/CMakeLists.txt
+++ b/cpp/tests/CMakeLists.txt
@@ -1,54 +1,54 @@
cmake_minimum_required(VERSION 2.8.11)
project(xreate-tests)
find_package(GTest REQUIRED)
INCLUDE_DIRECTORIES(${GTEST_INCLUDE_DIRS})
INCLUDE_DIRECTORIES("/usr/include/libxml2")
INCLUDE_DIRECTORIES($<TARGET_PROPERTY:xreate,INCLUDE_DIRECTORIES>)
# TESTS
#=========================
FIND_PACKAGE (LLVM REQUIRED)
message("LLVM_LIBRARY_DIRS: " ${LLVM_LIBRARY_DIRS})
link_directories(${LLVM_LIBRARY_DIRS})
set (LIBCLASP_PATH ${POTASSCO_PATH}/build/debug)
link_directories(${LIBCLASP_PATH})
#aux_source_directory(. TEST_FILES)
set(TEST_FILES
latereasoning.cpp
virtualization.cpp
exploitation.cpp
communication.cpp
polymorph.cpp
association.cpp
main.cpp
modules.cpp
attachments.cpp
ast.cpp
cfa.cpp
dfa.cpp
compilation.cpp
ExpressionSerializer.cpp
externc.cpp
types.cpp
- vendorAPI/clangAPI.cpp
- vendorAPI/xml2.cpp
- vendorAPI/json.cpp
+ #vendorsAPI/clangAPI.cpp
+ #vendorsAPI/xml2.cpp
+ #vendorsAPI/json.cpp
containers.cpp
interpretation.cpp
loops.cpp
#supplemental/versions-algorithm-data_dependency.cpp
effects-versions.cpp
)
add_executable(${PROJECT_NAME} ${TEST_FILES})
target_link_libraries(${PROJECT_NAME} xreate ${GTEST_LIBRARIES} pthread xml2 gcov)
add_custom_target (coverage
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/code-coverage.sh
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
diff --git a/cpp/tests/association.cpp b/cpp/tests/association.cpp
index 4b9ed90..23def6a 100644
--- a/cpp/tests/association.cpp
+++ b/cpp/tests/association.cpp
@@ -1,129 +1,129 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* association.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on August 12, 2017, 9:28 PM
*/
#include "xreatemanager.h"
-#include "clasplayer.h"
+#include "transcendlayer.h"
#include <gtest/gtest.h>
using namespace xreate;
using namespace std;
TEST(Association, test1){
std::string controller=
R"Code(
program(add).
)Code";
std::string script=
R"Code(
Annotation = type variant {
Num:: int,
String:: string,
Func:: {name::string, arguments::[Annotation]}
}.
extractCmd = function(program::Annotation):: Annotation; interpretation(force){
switch variant(program)::Annotation
case (Num){String("wrong expression")}
case (String){String("wrong expression")}
case (Func){program["arguments"][0]}
}
main= function:: int; entry{
x= 5::int.
y = 6::int.
program = intrinsic query("program")[0]::Annotation.
cmd = extractCmd(program)::Annotation; interpretation(force).
answer = switch variant(cmd)::int
case (Num) {0}
case (String){0}
case (Func){
switch(cmd["name"])::int
case("add"){x + y}
case default {0}
}.
answer
}
)Code";
std::unique_ptr<XreateManager> man(XreateManager::prepare(std::move(script)));
- man->clasp->addRawScript(move(controller));
+ man->transcend->addRawScript(move(controller));
int (*main)() = (int (*)())man->run();
int result = main();
ASSERT_EQ(11, result);
}
TEST(Association, QueryScope1){
std::string script = R"Code(
Annotation = type variant {
Num:: int,
String:: string,
Func:: {name::string, arguments::[Annotation]}
}.
func = function::int{10} //aux func in order to have few scopes
main = function:: int; entry {
scope = intrinsic query_scope()::Annotation.
answer = switch variant(scope):: int
case (Num) {scope}
case (String){-1}
case (Func){-1}.
answer
}
)Code";
std::unique_ptr<XreateManager> man(XreateManager::prepare(std::move(script)));
int (*main)() = (int (*)())man->run();
int result = main();
ASSERT_EQ(1, result);
}
//std::string script=
//R"Code(
//
//case context:: test1 {
//test= function::bool; registerTest {
// x = 8:: int.
//
// x == 8
//}}
//
//case context:: test2{
//test= function::bool{
// x = 3::int.
// y = 12::int.,
//
// (x+y) <> 25
//}}
//
//runTests= function::bool{
// tests = intrinsic query (registeredTests)::[Expression].
//
// loop fold(tests->test::Expression, true->result):: bool {
// shot = {
// context:: make context (test)
// test()
// }
//
// result and shot
// }
//}
//
//main= function:: int; entry{
// runTests()
//}
//)Code";
diff --git a/cpp/tests/cfa.cpp b/cpp/tests/cfa.cpp
index f520b39..1672da0 100644
--- a/cpp/tests/cfa.cpp
+++ b/cpp/tests/cfa.cpp
@@ -1,190 +1,190 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* testsCFG.cpp
*
* Created on: Jul 17, 2015
* Author: pgess <v.melnychenko@xreate.org>
*/
#include "xreatemanager.h"
#include "pass/dfapass.h"
#include "pass/cfapass.h"
#include "analysis/DominatorsTreeAnalysisProvider.h"
#include "analysis/cfagraph.h"
#include "gtest/gtest.h"
#include <boost/scoped_ptr.hpp>
#include <boost/smart_ptr/scoped_array.hpp>
using namespace xreate;
using namespace xreate::cfa;
using namespace std;
-TEST(CFA, testFunctionAnnotationsClasp){
+TEST(CFA, testFunctionAnnotationstranscend){
string&& program =
"f2 = function::int; annotationF2 {\n"
" 0\n"
"}\n"
"\n"
"f1 = function:: int; entry; annotationF1 {\n"
" f2() + 10\n"
"}";
details::tier1::XreateManager* man = details::tier1::XreateManager::prepare(move(program));
man->analyse();
- StaticModel answer = man->clasp->query("annotationF1");
+ StaticModel answer = man->transcend->query("annotationF1");
EXPECT_EQ(1, answer.size());
- answer = man->clasp->query("annotationF2");
+ answer = man->transcend->query("annotationF2");
EXPECT_EQ(1, answer.size());
}
TEST(CFA, testLoopContextExists){
details::tier1::XreateManager* man = details::tier1::XreateManager::prepare (
"interface(cfa){\n"
" operator fold:: annotation1.\n"
"}\n"
"\n"
"main = function:: int; entry {\n"
" x = [1..10]:: [int].\n"
" sum = loop fold (x->el:: int, 0->sum):: int {\n"
" el + sum + f1()\n"
" }. \n"
" sum\n"
"}"
"case context:: annotation1 {"
" f1 = function::int {\n"
" x = 0:: int. "
" x\n"
" }"
"}"
);
man->analyse();
- StaticModel model = man->clasp->query("annotation1");
- ScopePacked scopeIdActual = std::get<0>(ClaspLayer::parse<ScopePacked>(model.begin()->second));
+ StaticModel model = man->transcend->query("annotation1");
+ ScopePacked scopeIdActual = std::get<0>(TranscendLayer::parse<ScopePacked>(model.begin()->second));
CodeScope* scopeEntry = man->root->findFunction("main")->getEntryScope();
const Expression& exprSum = scopeEntry->getDefinition(scopeEntry->getSymbol("sum"));
CodeScope* scopeExpected = exprSum.blocks.front();
- ScopePacked scopeIdExpected = man->clasp->pack(scopeExpected);
+ ScopePacked scopeIdExpected = man->transcend->pack(scopeExpected);
ASSERT_EQ(scopeIdExpected, scopeIdActual);
}
TEST(CFA, DependenciesFnCall){
details::tier2::XreateManager* man = details::tier2::XreateManager::prepare(
R"Code(
a = function::int{
seq
{x = 0:: int. x}
{x = b():: int. x}::int
}
b = function::int {y = 0. y}
)Code");
CodeScope* scopeSeq1 = man->root->findFunction("a")->getEntryScope()->getBody().blocks.front();
CodeScope* scopeSeq2 = *(++man->root->findFunction("a")->getEntryScope()->getBody().blocks.begin());
CodeScope* scopeB = man->root->findFunction("b")->getEntryScope();
- ScopePacked psSeq1 = man->clasp->pack(scopeSeq1);
- ScopePacked psSeq2 = man->clasp->pack(scopeSeq2);
- ScopePacked psB = man->clasp->pack(scopeB);
+ ScopePacked psSeq1 = man->transcend->pack(scopeSeq1);
+ ScopePacked psSeq2 = man->transcend->pack(scopeSeq2);
+ ScopePacked psB = man->transcend->pack(scopeB);
CFAPass* pass = new CFAPass(man);
man->registerPass(pass, PassId::CFGPass);
man->executePasses();
const CFAGraph* report = dynamic_cast<CFAPassBasic*>(man->getPassById(PassId::CFGPass))->getReport();
auto dependencies = report->__dependencyRelations;
delete pass;
ASSERT_EQ(1, dependencies.count(psSeq2));
ASSERT_EQ(1, dependencies.count(psB));
}
TEST(CFA, DependenciesChildScope){
details::tier2::XreateManager* man = details::tier2::XreateManager::prepare(
R"Code(
a = function::int{
seq
{x = 0:: int. x}
{x=0::int. if(x>0)::int{1} else {0}}::int
}
)Code");
CodeScope* scopeSeq1 = man->root->findFunction("a")->getEntryScope()->getBody().blocks.front();
CodeScope* scopeSeq2 = *(++man->root->findFunction("a")->getEntryScope()->getBody().blocks.begin());
CodeScope* scopeIf1 = scopeSeq2->getBody().blocks.front();
CodeScope* scopeIf2 = *(++scopeSeq2->getBody().blocks.begin());
- ScopePacked psSeq1 = man->clasp->pack(scopeSeq1);
- ScopePacked psSeq2 = man->clasp->pack(scopeSeq2);
- ScopePacked psIf1 = man->clasp->pack(scopeIf1);
- ScopePacked psIf2 = man->clasp->pack(scopeIf2);
+ ScopePacked psSeq1 = man->transcend->pack(scopeSeq1);
+ ScopePacked psSeq2 = man->transcend->pack(scopeSeq2);
+ ScopePacked psIf1 = man->transcend->pack(scopeIf1);
+ ScopePacked psIf2 = man->transcend->pack(scopeIf2);
CFAPass* pass = new CFAPass(man);
man->registerPass(pass, PassId::CFGPass);
man->executePasses();
const CFAGraph* report = dynamic_cast<CFAPassBasic*>(man->getPassById(PassId::CFGPass))->getReport();
auto dependencies = report->__dependencyRelations;
delete pass;
ASSERT_EQ(0, dependencies.count(psSeq1));
ASSERT_EQ(1, dependencies.count(psSeq2));
ASSERT_EQ(1, dependencies.count(psIf1));
ASSERT_EQ(1, dependencies.count(psIf2));
for(auto rec: dependencies)
{
std::cout << rec.first << " " << rec.second << std::endl;
}
}
TEST(CFA, DomReportOneRoot){
std::string program =
R"CODE(
a = function:: int; entry{
seq
{x = 0:: int. x}
{x = 1:: int. x}::int
}
)CODE";
std::unique_ptr<details::tier2::XreateManager> man(details::tier2::XreateManager::prepare(move(program)));
CFAPass* pass = new CFAPass(man.get());
man->registerPass(pass, PassId::CFGPass);
pass->run();
- ScopePacked scope1 = man->clasp->pack(man->root->findFunction("a")->getEntryScope()->getBody().blocks.front());
- ScopePacked scope2 = man->clasp->pack(*++man->root->findFunction("a")->getEntryScope()->getBody().blocks.begin());
+ ScopePacked scope1 = man->transcend->pack(man->root->findFunction("a")->getEntryScope()->getBody().blocks.front());
+ ScopePacked scope2 = man->transcend->pack(*++man->root->findFunction("a")->getEntryScope()->getBody().blocks.begin());
dominators::DominatorsTreeAnalysisProvider* providerDomAnalysis = new dominators::DominatorsTreeAnalysisProvider();
providerDomAnalysis->run(pass->getReport());
dominators::DominatorsTreeAnalysisProvider::Dominators expectedFDom= {
{1, {0, 3}}
,{2, {1, 2}}
};
dominators::DominatorsTreeAnalysisProvider::Dominators expectedPostDom= {
{2, {0, 3}}
,{1, {1, 2}}
};
auto actualFDom = providerDomAnalysis->getForwardDominators();
auto actualPostDom = providerDomAnalysis->getPostDominators();
ASSERT_EQ(expectedFDom, actualFDom);
ASSERT_EQ(expectedPostDom, actualPostDom);
delete providerDomAnalysis;
delete pass;
}
diff --git a/cpp/tests/latereasoning.cpp b/cpp/tests/latereasoning.cpp
index c74916e..1e3f715 100644
--- a/cpp/tests/latereasoning.cpp
+++ b/cpp/tests/latereasoning.cpp
@@ -1,88 +1,109 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* latereasoning.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on April 21, 2018, 5:10 PM
*/
#include "xreatemanager.h"
-#include "clasplayer.h"
+#include "transcendlayer.h"
#include <boost/format.hpp>
#include "gtest/gtest.h"
using namespace xreate;
TEST(LateReasoning, test2) {
FILE* input = fopen("scripts/latereasoning/test2.xreate", "r");
assert(input != nullptr);
std::unique_ptr<XreateManager> man(XreateManager::prepare(input));
int (*main)() = (int (*)())man->run();
int result = main();
ASSERT_EQ(3, result);
}
/**
* Test plan:
* - add late annotation(several variants)
* - define late bindings
* - get late variant wrt defined bindings
**/
TEST(LateReasoning, PutAndGetLateAnnotation1) {
#define FORMATSYMBOL(s) (formatSymb % s.identifier % s.version % s.scope).str()
Attachments::init<LateBinding>();
Attachments::init<versions::VariableVersion>();
- std::unique_ptr<ClaspLayer> clasp(new ClaspLayer());
+ std::unique_ptr<TranscendLayer> transcend(new TranscendLayer());
std::unique_ptr<CodeScope> scope(new CodeScope(nullptr));
Symbol symbA = scope->addDefinition(Atom<Identifier_t>("a"), Expression());
Symbol symbB = scope->addDefinition(Atom<Identifier_t>("b"), Expression());
Symbol symbC = scope->addDefinition(Atom<Identifier_t>("c"), Expression());
Symbol symbTarget = scope->addDefinition(Atom<Identifier_t>("target"), Expression());
- SymbolPacked symbpA = clasp->pack(symbA, "a");
- SymbolPacked symbpB = clasp->pack(symbB, "b");
- SymbolPacked symbpC = clasp->pack(symbC, "c");
- SymbolPacked symbpTarget = clasp->pack(symbTarget, "target");
+ SymbolPacked symbpA = transcend->pack(symbA, "a");
+ SymbolPacked symbpB = transcend->pack(symbB, "b");
+ SymbolPacked symbpC = transcend->pack(symbC, "c");
+ SymbolPacked symbpTarget = transcend->pack(symbTarget, "target");
boost::format formatSymb("s(%1%,%2%,%3%)");
boost::format formatLateAnnotation("late(%1%, (%2%, %3%, %4%), (%5%, %6%, %7%), %8%).");
//Add `variant1` variant
- clasp->addRawScript((formatLateAnnotation
+ transcend->addRawScript((formatLateAnnotation
% FORMATSYMBOL(symbpTarget)
% FORMATSYMBOL(symbpA) % FORMATSYMBOL(symbpB) % FORMATSYMBOL(symbpC)
% "guard1" % "guard1" % "guard1"
% "result(variant1)"
). str());
//Add `result2` variant
- clasp->addRawScript((formatLateAnnotation
+ transcend->addRawScript((formatLateAnnotation
% FORMATSYMBOL(symbpTarget)
% FORMATSYMBOL(symbpA) % FORMATSYMBOL(symbpB) % FORMATSYMBOL(symbpC)
% "guard2" % "guard2" % "guard2"
% "result(variant2)"
). str());
- clasp->run();
+ transcend->run();
//Define keys
Attachments::put<LateBinding>(symbA, Expression(Operator::CALL, {Atom<Identifier_t>("guard2")}));
Attachments::put<LateBinding>(symbB, Expression(Operator::CALL, {Atom<Identifier_t>("guard2")}));
Attachments::put<LateBinding>(symbC, Expression(Operator::CALL, {Atom<Identifier_t>("guard2")}));
//Fetch late annotation
- ReasoningModel model = clasp->queryCompiled();
+ ReasoningModel model = transcend->queryCompiled();
StaticModel answer = model.queryLate("result", symbpTarget);
ASSERT_EQ(1, answer.size());
- std::tuple<std::string> answerParsed = clasp->parse<std::string>(answer.begin()->second);
+ std::tuple<std::string> answerParsed = transcend->parse<std::string>(answer.begin()->second);
ASSERT_STREQ("variant2", std::get<0>(answerParsed).c_str());
-}
\ No newline at end of file
+}
+
+TEST(LateReasoning, Syntax1) {
+ XreateManager* man = XreateManager::prepare(R"Code(
+test = function:: int {
+ x = 0::int.
+ y1= switch late (x)::int{0}.
+ y2= switch late(x+y1->a::int)::int{1}.
+ y1+y2
+}
+)Code");
+
+ CodeScope* scope = man->root->findFunction("test")->getEntryScope();
+ Expression y1 = scope->getDefinition(scope->getSymbol("y1"));
+ Expression y2 = scope->getDefinition(scope->getSymbol("y2"));
+
+ ASSERT_EQ(1, y1.bindings.size());
+ ASSERT_STRCASEEQ("x", y1.bindings.at(0).c_str());
+
+ ASSERT_EQ(1, y2.bindings.size());
+ ASSERT_STRCASEEQ("a", y2.bindings.at(0).c_str());
+}
diff --git a/cpp/tests/polymorph.cpp b/cpp/tests/polymorph.cpp
index b7a9cf7..226218f 100644
--- a/cpp/tests/polymorph.cpp
+++ b/cpp/tests/polymorph.cpp
@@ -1,106 +1,106 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* polymorph.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on October 11, 2017, 8:37 PM
*/
#include "xreatemanager.h"
#include "ast.h"
#include <list>
#include "gtest/gtest.h"
-#include "clasplayer.h"
+#include "transcendlayer.h"
using namespace std;
using namespace xreate;
using namespace std;
TEST(Polymorphs, ast1) {
xreate::XreateManager* man = xreate::XreateManager::prepare(
R"CODE(
guard:: a {
test = function:: int {0}
}
guard:: b {
test = function:: int {1}
}
main = function:: int; entry { test() }
)CODE");
const std::list<ManagedFnPtr>& specs = man->root->getFunctionSpecializations("test");
ASSERT_EQ(2, specs.size());
auto itSpecs = specs.begin();
ASSERT_EQ("a", (*itSpecs)->guard.getValueString());
itSpecs++;
ASSERT_EQ("b", (*itSpecs)->guard.getValueString());
}
TEST(Polymorphs, StaticCall1) {
xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
R"CODE(
import raw("scripts/dfa/polymorphism.lp").
guard:: a {
test = function:: int {0}
}
guard:: b {
test = function:: int {1}
}
main = function:: int; entry { test()::int; callguard(b);dfa_polym(ret)}
)CODE");
man->analyse();
int (*main)() = (int (*)()) man->run();
ASSERT_EQ(1, main());
}
TEST(Polymorphs, LateCall1){
Attachments::init<LateBinding>();
xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
R"CODE(
guard:: a {
test = function:: int {0}
}
guard:: b {
test = function:: int {1}
}
main = function:: int; entry{
key = 0:: int; _guard.
if (key == 0)::int {
test()::int; dfa_polym(late)
} else {0}
}
)CODE");
- man->clasp->addRawScript(
+ man->transcend->addRawScript(
R"RULE(
late(SymbRet, list(SymbGuard), list(a), dfa_callguard(a)):-
bind(SymbRet, dfa_polym(late));
bind(SymbGuard, _guard).
late(SymbRet, list(SymbGuard), list(b), dfa_callguard(b)):-
bind(SymbRet, dfa_polym(late));
bind(SymbGuard, _guard).
)RULE");
man->analyse();
CodeScope* scopeMainBody = man->root->findFunction("main")->getEntryScope();
Symbol symbKey = Symbol{scopeMainBody->getSymbol("key"), scopeMainBody};
Attachments::put<LateBinding>(symbKey, Expression(Operator::CALL, {Atom<Identifier_t>("b")}));
int (*main)() = (int (*)()) man->run();
ASSERT_EQ(1, main());
-}
\ No newline at end of file
+}
diff --git a/documentation-api/folders.dox b/documentation-api/folders.dox
index d9dec8a..1df879e 100644
--- a/documentation-api/folders.dox
+++ b/documentation-api/folders.dox
@@ -1,16 +1,16 @@
/**
* \dir analysis
- * \brief Data structures and providers for analysis step. Everything that depends on reasoner Clasp API.
+ * \brief Data structures and providers for analysis step. Everything that depends on Clasp reasoner's API.
*
* \dir aux
* \brief Auxiliary files
*
* \dir compilation
* \brief Code related to compilation step. Everything that depends on compiler toolchain LLVM internals
*
* \dir pass
* \brief Various passes to gather data and perforrm analysis and compilation
*
* \dir query
* \brief Code for exrtacting solutions from reasoner output and influence compilation
*/
diff --git a/documentation-api/overview.dox b/documentation-api/overview.dox
index 29632cb..99d2bb3 100644
--- a/documentation-api/overview.dox
+++ b/documentation-api/overview.dox
@@ -1,73 +1,73 @@
/**
* \mainpage Xreate Internals
* \tableofcontents
* \attention For installation and examples see [Instruction: First Steps](/w/instructions/first=steps).
*
* In a nutshell, xreate::XreateManager is an entry point of Xreate API and clients should start off by instantiating it.
*
* xreate::XreateManager is convenient wrapper to control all internal work-flow consisting of steps as follows:
* - Parsing
* - Intermediate Passes
* - Reasoning
* - Compilation
*
* \section grammar_sect Grammar
* Xreate's grammar located in two files in COCO parser generator's format
* - `/grammar/xreate.ATG` : main Xreate's grammar file
* - `/grammar/modules.ATG` : additional grammar to support modules management. See xreate::modules::XreateManagerDecoratorModules and [Modules Explanation](/w/concepts/modules/) for details
* \section parsing_sect Parsing
* xreate::AST represents Xreate's syntax tree. It's produced by `Scanner` and `Parser` themselves generated by external tool Coco Parser Generator
*
* \section var_passes_sect Intermediate Passes
* Once xreate::AST is built, xreate::XreateManager runs number of passes as a preparation
- * for *reasoning*(xreate::ClaspLayer) and *compilation*(xreate::CompilePass).
+ * for *reasoning*(xreate::TranscendLayer) and *compilation*(xreate::CompilePass).
*
* There is xreate::Attachments to address need of communication between various passes and stages.
*
* Currently there are following passes:
* - xreate::cfa::CFAPass to perform Control Flow Analysis(CFA). Analysis' output stored in xreate::cfa::CFAGraph
* - xreate::dfa::DFAPass to perform Data Flow Analysis(DFA). Output stored in xreate::dfa::DFAGraph
* - xreate::interpretation::InterpretationPass to perform Interpretation analysis. See [Interpretation Overview](w/concepts/dfa)
* - xreate::versions::VersionsPass to perform Versions Analysis. See [Versions Overview](w/concepts/versions)
*
* Each pass should inherit xreate::IPass interface or xreate::AbstractPass as a more convenient wrapper.
* xreate::PassManager is base class to manage passes and xreate::XreateManager derives xreate::PassManager to control builtin passes.
*
* \section reasoning_sect Reasoning
- * xreate::ClaspLayer is wrapper over external Clasp reasoner.
+ * xreate::TranscendLayer is wrapper over external Clasp reasoner.
* Data gathered by previously executed passes is composed(see xreate::IAnalysisReport, \ref analysis/aux.h for details) into _logic program_ as a _text_ according to Clasp reasoner's ASP syntax.
* Current list of data sources is:
* - Raw scripts. Client could append arbitrary ASP script to _logic program_
* - Includes. There is possibility to point out external files with ASP scripts to append to _logic program_
* - Diagnostic rules. Rules that produce diagnostic messages during compilation(warnings) or even able to halt compilation with errors
* - DFA data. See xreate::dfa::DFAGraph
* - CFA data. See xreate::cfa::CFAGraph
* - Dominators Analysis. See xreate::dominators::DominatorsTreeAnalysisProvider
* - Context rules. See xreate::ContextRule and general [Context Explanation](/w/concepts/context)
*
* Following analyses are performed currently bypassing ASP reasoner:
* - \ref typeinference.h Type Inference
* - xreate::interpretation::InterpretationPass Interpretation analysis
* - xreate::versions::VersionsPass Versions analysis
*
- * Output of Clasp reasoner is recognized and accessed via *queries*.
+ * Output of the external Clasp reasoner is recognized and accessed via *queries*.
* Query is an interface between reasoner' output and rest of Xreate.
* Each query inherits xreate::IQuery interface. Currently there are queries as follows:
* - xreate::containers::Query to catch solutions regarding Containers implementation. See [Containers Explanation](/w/concepts/containers)
* - xreate::context::ContextQuery to catch solution regarding Context. See [Context Explanation](/w/concepts/context)
*
* \section compilation_sect Compilation
- * xreate::CompilePass iterates over xreate::AST tree and produces executable code fed by data(via xreate::Attachments) gathered by previous passes as well as data via queries(xreate::IQuery) from Clasp reasoner.
+ * xreate::CompilePass iterates over xreate::AST tree and produces executable code fed by data(via xreate::Attachments) gathered by previous passes as well as data via queries(xreate::IQuery) from the external Clasp reasoner.
* Compilation done using xreate::LLVMLayer(wrapper over LLVM byte machine) and based on following aspects:
* - Containers support. See \ref compilation/containers.h
* - Late Conext compilation. See xreate::context::LateContextCompiler2
* - Interpretation support. See xreate::interpretation::TargetInterpretation
* - Loop saturation support. See xreate::compilation::TransformerSaturation
* - External Code access. See xreate::ExternLayer(wrapper over Clang library)
*
*\subsection compilation_adaptability Adaptability
*
* xreate::CompilePass's architecture allows adaptability in different ways
* to alter function-level, code scope-level compilation and so on. More details in xreate::CompilePass description.
*/
diff --git a/documentation/development/files.remarkup b/documentation/development/files.remarkup
index 46a7dba..c6dc0a3 100644
--- a/documentation/development/files.remarkup
+++ b/documentation/development/files.remarkup
@@ -1,46 +1,46 @@
|Filename|Description|Unit-tests
| ----- | ----- | -----
| analysis/cfagraph.*, /pass/cfapass.* | [[Analysis/cfa|CFA]] | tests/cfa.cpp
| analysis/DominatorsTreeAnalysisProvider.* | [[Analysis/dominators_analysis|Dominators analysis]] | tests/cfa.cpp
| query/context.* |[[Concepts/context|CFA/Context support]] | tests/context.cpp
| compilation/latecontextcompiler2.*, serialization/expressionserializer* | [[Concepts/context#late-context|Late context support]] | tests/context.cpp, tests/ExpressionSerializer.cpp
| src/contextrule.h | [[Concepts/context#context-rules|Context rules support]] |
| analysis/dfagraph.*, /pass/dfapass.* | [[Analysis/dfa|DFA]] | tests/dfa.cpp
| compilation/advanced.* | Additional constructions compilation |
| compilation/containers.*, query/containers.* |[[Concepts/containers|Containers support]]|tests/containers.cpp
| pass/interpretationpass.*, compilation/targetinterpretation.* | [[Concepts/dsl|DSL/Interpretation]] | tests/interpretation.cpp
| pass/adhocpass.*| [[Concepts/adhocs|"Adhocs" feature support]] |tests/adhoc.cpp
| src/ast.*, pass/compilepass.* | [[Syntax|Main compilation routines]] | tests/compilation.cpp, tests/basic.cpp, tests/loops.cpp, tests/ast.cpp, tests/types.cpp
| pass/loggerpass.* | Logging support |
| pass/rulespass.* | logic rules support |
-| src/clasplayer.* | [[Articles/logic_inference|Logic inference support]] |
+| src/transcendlayer.* | [[Articles/logic_inference|Logic inference support]] |
| src/llvmlayer.* | Low level byte code compilation|
| src/ExternLayer.* | Foreign Function Interface(FFI/C) support | tests/externc.cpp
| src/passmanager.* | Manages analysis and compilation passes|
---
analysis
file:///private/prg/code/xreate/cpp/src/analysis/aux.h
file:///private/prg/code/xreate/cpp/src/analysis/aux.cpp
compilation
file:///private/prg/code/xreate/cpp/src/compilation/targets.h
file:///private/prg/code/xreate/cpp/src/compilation/transformations.h
file:///private/prg/code/xreate/cpp/src/compilation/transformations.cpp
pass/
file:///private/prg/code/xreate/cpp/src/pass/abstractpass.h
file:///private/prg/code/xreate/cpp/src/pass/abstractpass.cpp
query:
src
src/attachments.*
file:///private/prg/code/xreate/cpp/src/serialization.h
file:///private/prg/code/xreate/cpp/src/utils.h
tests
file:///private/prg/code/xreate/cpp/tests/testClangAPI.cpp
file:///private/prg/code/xreate/cpp/tests/testJson.cpp
- file:///private/prg/code/xreate/cpp/tests/testLibXml2.cpp
\ No newline at end of file
+ file:///private/prg/code/xreate/cpp/tests/testLibXml2.cpp
diff --git a/grammar/xreate.ATG b/grammar/xreate.ATG
index 4e3818e..77cf607 100644
--- a/grammar/xreate.ATG
+++ b/grammar/xreate.ATG
@@ -1,644 +1,664 @@
//TODO add ListLiteral
//TODO ExprTyped: assign default(none) type
#include "ast.h"
#include "ExternLayer.h"
#include <string>
#include <stack>
#define wprintf(format, ...) \
char __buffer[100]; \
wcstombs(__buffer, format, 100); \
fprintf(stderr, __buffer, __VA_ARGS__)
using namespace std;
COMPILER Xreate
details::inconsistent::AST* root = nullptr; // current program unit
void ensureInitalizedAST(){
if (root == nullptr) root = new details::inconsistent::AST();
}
struct {
std::stack<CodeScope*> scopesOld;
CodeScope* scope = nullptr;
} context;
void pushContextScope(CodeScope* scope){
context.scopesOld.push(context.scope);
context.scope = scope;
}
void popContextScope(){
context.scope = context.scopesOld.top();
context.scopesOld.pop();
}
int nextToken()
{
scanner->ResetPeek();
return scanner->Peek()->kind;
}
bool checkTokenAfterIdent(int key){
if (la->kind != _ident) return false;
return nextToken() == key;
}
bool checkParametersList()
{
return la->kind == _ident && nextToken() == _lparen;
}
bool checkInfix()
{
return la->kind == _ident && nextToken() == _ident;
}
bool checkIndex()
{
return la->kind == _ident && nextToken() == _lbrack;
}
bool checkFuncDecl()
{
if (la->kind != _ident) return false;
int token2 = nextToken();
int token3 = scanner->Peek()->kind;
return token2 == _assign && (token3 == _function || token3 == _pre);
}
-
-
bool checkAssignment()
{
if (la->kind != _ident) return false;
scanner->ResetPeek();
int token2 = scanner->Peek()->kind;
if (token2 == _lcurbrack) {
scanner->Peek();
int token3 = scanner->Peek()->kind;
if (token3 != _rcurbrack) return false;
int token4 = scanner->Peek()->kind;
return token4 == _assign;
}
return token2 == _assign;
}
void recognizeIdentifier(Expression& i){
if (!context.scope->recognizeIdentifier(i)){
root->postponeIdentifier(context.scope, i);
}
}
enum SwitchKind{SWITCH_NORMAL, SWITCH_META};
CHARACTERS
letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".
any = ANY - '"'.
digit = "0123456789".
cr = '\r'.
lf = '\n'.
tab = '\t'.
TOKENS
ident = (letter | '_') {letter | digit | '_'}.
number = (digit | '-' digit) {digit}.
string = '"' { any } '"'.
function = "function".
pre = "pre".
lparen = '('.
rparen = ')'.
lbrack = '['.
rbrack = ']'.
lcurbrack = '{'.
rcurbrack = '}'.
equal = "==".
assign = '='.
implic = '-' '>'.
colon = ':'.
context = "context".
tagcolon = "::".
lse = "<=".
lss = "<".
gte = ">=".
gtr = ">".
ne1 = "!=".
ne2= "<>".
COMMENTS FROM "/*" TO "*/" NESTED
COMMENTS FROM "//" TO lf
IGNORE cr + lf + tab
PRODUCTIONS
Xreate = (. Function* function; ensureInitalizedAST(); .)
{( RuleDecl
| InterfaceData | Imprt | GuardSection
| IF(checkFuncDecl()) FDecl<function> (. root->add(function); .)
| TDecl
| SkipModulesSection
)} (. .)
.
Ident<std::wstring& name>
= ident (. name = t->val; .).
VarIdent<Expression& e>
= ident (. e = Expression(Atom<Identifier_t>(t->val)); .)
[ lcurbrack (
ident (. SemErr(coco_string_create("var version as ident is not implemented yet")); .)
| number (. Attachments::put<versions::VariableVersion>(e, Atom<Number_t>(t->val).get()); .)
) rcurbrack ]
.
FDecl<Function*& f> = (. std::wstring fname; std::wstring argName; TypeAnnotation typIn; TypeAnnotation typOut; bool flagIsPrefunct = false; Expression binding; .)
Ident<fname> assign
[pre (. flagIsPrefunct = true; .)]
function (. f = new Function(fname); f->isPrefunction = flagIsPrefunct; CodeScope* entry = f->getEntryScope(); .)
['(' Ident<argName> tagcolon ExprAnnotations<binding> (. f->addBinding(Atom<Identifier_t>(argName), move(binding)); .)
{',' Ident<argName> tagcolon ExprAnnotations<binding> (. f->addBinding(Atom <Identifier_t>(argName), move(binding));.)
} ')']
[ tagcolon
( IF(flagIsPrefunct) FnTag<f>
| Type<typOut>
)
{';' FnTag<f> }]
BDecl<entry> (. const_cast<Expression&>(entry->getBody()).bindType(move(typOut));.)
.
GuardSection<>= (. Expression guard; Function* f; .)
"guard" tagcolon MetaSimpExpr<guard>
lcurbrack { FDecl<f> (. f->guard = guard; root->add(f); .)
} rcurbrack.
/**
* TYPES
*
*/
TypeTerm<TypePrimitive& typ> = (. std::wstring tid; .)
("string" (. typ = TypePrimitive::String;.)
| "num" (. typ = TypePrimitive::Num;.)
| "int" (. typ = TypePrimitive::Int;.)
| "float" (. typ = TypePrimitive::Float;.)
| "bool" (. typ = TypePrimitive::Bool; .)
| "i8" (. typ = TypePrimitive::I8; .)
| "i32" (. typ = TypePrimitive::I32; .)
| "i64" (. typ = TypePrimitive::I64; .)
).
Type<TypeAnnotation& typ> = (. TypeAnnotation typ2; TypePrimitive typ3; std::wstring tid, field; .)
(
TList<typ>
| TStruct<typ>
| TVariant<typ>
| TypeTerm<typ3> (. typ = typ3; .)
| IF (checkIndex()) Ident<tid> lbrack
Ident<field> (. typ = TypeAnnotation(TypeOperator::ACCESS, {}); typ.__valueCustom = Atom<Identifier_t>(tid).get(); typ.fields.push_back(Atom<Identifier_t>(field).get()); .)
{',' Ident<field> (. typ.fields.push_back(Atom<Identifier_t>(field).get()); .)
} rbrack
| Ident<tid> (. typ = TypeAnnotation(TypeOperator::CUSTOM, {}); typ.__valueCustom = Atom<Identifier_t>(tid).get(); .)
['(' Type<typ2> (. typ.__operator = TypeOperator::CALL; typ.__operands.push_back(typ2); .)
{',' Type<typ2> (. typ.__operands.push_back(typ2); .)
} ')']
) .
TList<TypeAnnotation& typ> = (. TypeAnnotation ty; .)
'[' Type<ty> ']' (. typ = TypeAnnotation(TypeOperator::LIST, {ty}); .)
.
TStruct<TypeAnnotation& typ> = (. TypeAnnotation t; std::wstring key; size_t keyCounter=0; .)
lcurbrack
(
IF(checkTokenAfterIdent(_tagcolon)) Ident<key> tagcolon Type<t>
| Type<t> (. key = to_wstring(keyCounter++); .)
) (. typ = TypeAnnotation(TypeOperator::LIST_NAMED, {t}); typ.fields.push_back(Atom<Identifier_t>(key).get()); .)
{',' (
IF(checkTokenAfterIdent(_tagcolon)) Ident<key> tagcolon Type<t>
| Type<t> (. key = to_wstring(keyCounter++); .)
) (. typ.__operands.push_back(t); typ.fields.push_back(Atom<Identifier_t>(key).get()); .)
} rcurbrack.
TVariant<TypeAnnotation& typ>= (. TypeAnnotation t, typVoid(TypeOperator::LIST_NAMED, {}); std::vector<TypeAnnotation> operands; std::vector<Atom<Identifier_t>> keys; std::wstring variant; .)
"variant" lcurbrack
Ident<variant> (. t=typVoid; .)
[tagcolon Type<t>] (. keys.push_back(Atom<Identifier_t>(variant)); operands.push_back(t); .)
{',' Ident<variant> (. t=typVoid; .)
[tagcolon Type<t>] (. keys.push_back(Atom<Identifier_t>(variant)); operands.push_back(t); .)
}
rcurbrack (. typ = TypeAnnotation(TypeOperator::VARIANT, {}); typ.__operands = operands; typ.addFields(std::move(keys)); .)
.
TDecl = (. TypeAnnotation t; std::wstring tname, arg; std::vector<Atom<Identifier_t>> args; .)
Ident<tname> assign "type"
['(' Ident<arg> (. args.push_back(Atom<Identifier_t>(arg)); .)
{',' Ident<arg> (. args.push_back(Atom<Identifier_t>(arg)); .)
} ')']
Type<t>'.' (. t.addBindings(move(args)); root->add(move(t), Atom<Identifier_t>(tname)); .)
.
ContextDecl<CodeScope * scope> = (. Expression tag; .)
context tagcolon
MetaSimpExpr<tag> (. scope->tags.push_back(tag); .)
{';' MetaSimpExpr<tag> (. scope->tags.push_back(tag); .)
}.
VDecl<CodeScope* f> = (. std::wstring vname; Expression var, value;.)
VarIdent<var> assign ExprTyped<value> (. Symbol identSymbol = f->addDefinition(move(var), move(value));
Attachments::put<SymbolAlias>(value, identSymbol);
.)
.
BDecl<CodeScope* scope> = lcurbrack (. Expression body; pushContextScope(scope); .)
{(IF(checkAssignment()) VDecl<scope> '.'
| RuleContextDecl<scope>
| ContextDecl<scope>'.'
| ExprTyped<body> (. scope->setBody(body); Attachments::put<SymbolAlias>(body, Symbol{ScopedSymbol::RetSymbol, scope});.)
)}
rcurbrack (. popContextScope(); .)
.
IfDecl<Expression& e> = (. Expression cond; ManagedScpPtr blockTrue = root->add(new CodeScope(context.scope)); ManagedScpPtr blockFalse = root->add(new CodeScope(context.scope)); .)
"if" '(' Expr<cond> ')' (. e = Expression(Operator::IF, {cond}); .)
tagcolon ExprAnnotations<e>
BDecl<&*blockTrue> "else" BDecl<&*blockFalse> (. e.addBlock(blockTrue); e.addBlock(blockFalse); .)
.
LoopDecl<Expression& e> =
(. Expression eIn, eAcc, eFilters; std::wstring varEl, varAcc, contextClass; Expression tagsEl;
ManagedScpPtr block = root->add(new CodeScope(context.scope)); .)
"loop"
("map" '(' Expr<eIn> implic Ident<varEl> (. e = Expression(Operator::MAP, {eIn}); .)
tagcolon ExprAnnotations<tagsEl> ')' tagcolon ExprAnnotations<e>
(.
e.addBindings({Atom<Identifier_t>(varEl)});
block->addBinding(Atom<Identifier_t>(varEl), move(tagsEl));
.)
BDecl<&*block>
(. e.addBlock(block); .)
|"fold"
("inf" '(' Expr<eAcc> implic Ident<varAcc> ')'
(.
e = Expression(Operator::FOLD_INF, {eAcc});
e.addBindings({Atom<Identifier_t>(varAcc)});
block->addBinding(Atom<Identifier_t>(varAcc), Expression());
.)
tagcolon ExprAnnotations<e> BDecl<&*block>
(. e.addBlock(block); .)
| '(' Expr<eIn> implic Ident<varEl> tagcolon ExprAnnotations<tagsEl> ['|' Expr<eFilters> ] ',' Expr<eAcc> implic Ident<varAcc>')'
(.
e = Expression(Operator::FOLD, {eIn, eAcc});
e.addBindings({Atom<Identifier_t>(varEl), Atom<Identifier_t>(varAcc)});
.)
tagcolon ExprAnnotations<e>
(.
block->addBinding(Atom<Identifier_t>(varEl), move(tagsEl));
block->addBinding(Atom<Identifier_t>(varAcc), Expression());
.)
BDecl<&*block>
(. e.addBlock(block); .)
)
- | "context" '(' string (. contextClass = t->val; .)
- ')' BDecl<&*block>
- (. e = Expression(Operator::LOOP_CONTEXT, {Expression(Atom<String_t>(std::move(contextClass)))});
- e.addBlock(block);
- .)
).
// Switches
SwitchDecl<Expression& eSwitch, SwitchKind flagSwitchKind> = (. TypeAnnotation typ; eSwitch = Expression(Operator::SWITCH, {}); Expression eCondition; Expression tag;.)
"switch"
(
- SwitchVariantDecl<eSwitch>
+ SwitchVariantDecl<eSwitch>
+ | SwitchLate<eSwitch>
| lparen ExprTyped<eCondition> rparen tagcolon ExprAnnotations<eSwitch> (. eSwitch.operands.push_back(eCondition);.)
CaseDecl<eSwitch, flagSwitchKind> {CaseDecl<eSwitch, flagSwitchKind>}
)
.
CaseDecl<Expression& outer, SwitchKind flagSwitchKind> = (. ManagedScpPtr scope = root->add(new CodeScope(context.scope)); Expression condition; .)
"case"
( IF(flagSwitchKind == SWITCH_META)
lparen MetaSimpExpr<condition> rparen BDecl<&*scope> (. Expression exprCase(Operator::CASE, {}); exprCase.addTags({condition}); exprCase.addBlock(scope); outer.addArg(move(exprCase));.)
| "default" BDecl<&*scope> (. Expression exprCase(Operator::CASE_DEFAULT, {});
exprCase.addBlock(scope);
outer.operands.insert(++outer.operands.begin(), exprCase); .)
| lparen CaseParams<&*scope> rparen (. ManagedScpPtr scopeBody = root->add(new CodeScope(&*scope)); Expression exprCase(Operator::CASE, {}); .)
BDecl<&*scopeBody> (. exprCase.addBlock(scope); exprCase.addBlock(scopeBody); outer.addArg(move(exprCase)); .)
).
CaseParams<CodeScope* scope> = (. Expression condition; Expression guard(Operator::LOGIC_AND, {}); pushContextScope(scope); .)
ExprTyped<condition> (. guard.addArg(Expression(condition)); .)
{',' ExprTyped<condition> (. guard.addArg(Expression(condition)); .)
} (. scope->setBody(guard); popContextScope(); .)
.
+SwitchLate<Expression& expr> =
+ (.
+ std::wstring aliasCondition; Expression exprCondition;
+ expr = Expression(Operator::SWITCH_LATE, {});
+ ManagedScpPtr scope = root->add(new CodeScope(context.scope));
+ .)
+
+ "late" lparen Expr<exprCondition> [implic Ident<aliasCondition>] [tagcolon ExprAnnotations<exprCondition>] rparen
+ tagcolon ExprAnnotations<expr> BDecl<&*scope>
+ (.
+ expr.addArg(Expression(exprCondition));
+ if(aliasCondition.empty()){
+ if(exprCondition.__state != Expression::IDENT){
+ SemErr(coco_string_create("An identifier expected in the short form"));
+ return;
+ }
+
+ //Use exprCondition as id
+ expr.addBindings({Atom<Identifier_t>(string(exprCondition.getValueString()))});
+ } else {
+ //Use aliasCondition
+ expr.addBindings({Atom<Identifier_t>(aliasCondition)});
+ }
+ .)
+.
+
SwitchVariantDecl<Expression& expr> =
(. Expression varTested; std::wstring varAlias; bool flagAliasFound = false; expr = Expression(Operator::SWITCH_VARIANT, {}); .)
"variant" lparen Expr<varTested> [implic Ident<varAlias>
(. flagAliasFound = true; .)
] [tagcolon ExprAnnotations<varTested>] rparen tagcolon ExprAnnotations<expr>
(. expr.addArg(std::move(varTested));
if (flagAliasFound) {
expr.addBindings({Atom<Identifier_t>(varAlias)});
} else {
if(varTested.__state == Expression::IDENT){
expr.addBindings({Atom<Identifier_t>(string(varTested.getValueString()))});
}
}
.)
CaseVariantDecl<expr> {CaseVariantDecl<expr>}
.
CaseVariantDecl<Expression& expr> = (. ManagedScpPtr scope = root->add(new CodeScope(context.scope)); std::wstring key; scope->addBinding(Atom<Identifier_t>(string(expr.bindings.front())), Expression()); .)
"case" lparen Ident<key> rparen (. expr.addArg(root->recognizeVariantConstructor(Atom<Identifier_t>(std::move(key)))); .)
BDecl<&*scope> (. expr.addBlock(scope); .)
.
IntrinsicDecl<Expression& outer>= (. std::wstring name; .)
"intrinsic" Ident< name> (. outer = Expression(Operator::CALL_INTRINSIC, {}); outer.setValue(Atom<Identifier_t>(name)); .)
lparen [CalleeParams<outer>] rparen .
SequenceDecl<Expression& sequence> = (. sequence = Expression(); sequence.setOp(Operator::SEQUENCE); ManagedScpPtr scope = root->add(new CodeScope(context.scope)); .)
"seq" BDecl<&*scope> (. sequence.blocks.push_back(&*scope); scope = root->add(new CodeScope(&*scope)); .)
{ (. scope = root->add(new CodeScope(&*scope)); .)
BDecl<&*scope> (. sequence.blocks.push_back(&*scope); .)
}.
/*============================ INTERFACES ===============================*/
Imprt<> =
"import" "raw" lparen string (. root->__rawImports.push_back(Atom<String_t>(t->val).get()); .)
rparen '.'.
InterfaceData<> = "interface" '('
( "dfa" ')' InterfaceDFA
| "extern-c" ')' InterfaceExternC
| "cfa" ')' InterfaceCFA
).
InterfaceExternC<> = (. ExternData data; .)
'{' {IncludeExternDecl<data> | LibExternDecl<data> } '}'
(. root->addExternData(move(data)); .)
.
LibExternDecl<ExternData& data> = (. std::wstring pkgname, libname; .)
Ident<libname> assign "library" tagcolon "pkgconfig"
'(' string (. pkgname = t->val; .)
')' '.' (. data.addLibrary(Atom<Identifier_t>(libname), Atom<String_t>(pkgname)); .)
.
IncludeExternDecl<ExternData& data> = (. Expression inc; .)
"include" StructLiteral<inc> '.' (. data.addIncludeDecl(move(inc)); .)
.
InterfaceDFA<> = '{' { InstructDecl } '}' .
InstructDecl = (.Operator op; Expression tag;
Expression scheme;
std::vector<Expression>& tags = scheme.operands;
tags.push_back(Expression()); /* return value */ .)
"operator" InstructAlias<op> tagcolon '(' (.scheme.setOp(op); .)
[
MetaSimpExpr<tag> (. tags.push_back(tag); .)
{
',' MetaSimpExpr<tag> (. tags.push_back(tag); .)
}
] ')' [ implic MetaSimpExpr<tag> (. tags[0] = tag; .)
] (. root->addDFAData(move(scheme)); .)
'.'.
InstructAlias<Operator& op> =
(
"map" (. op = Operator::MAP; .)
| "list_range" (. op = Operator::LIST_RANGE; .)
| "list" (. op = Operator::LIST; .)
| "fold" (. op = Operator::FOLD; .)
| "index" (. op = Operator::INDEX; .)
).
InterfaceCFA<> = '{' { InstructCFADecl } '}' .
InstructCFADecl<> = (.Operator op; Expression tag;
Expression scheme;
std::vector<Expression>& tags = scheme.operands; .)
"operator" InstructAlias<op> tagcolon (. scheme.setOp(op); .)
[
MetaSimpExpr<tag> (. tags.push_back(tag); .)
{
',' MetaSimpExpr<tag> (. tags.push_back(tag); .)
}
] '.' (. root->addInterfaceData(CFA, move(scheme)); .).
/*============================ METAPROGRAMMING ===============================*/
// TagsDecl<CodeScope* f> = (. Expression tag; TagModifier mod = TagModifier::NONE; .)
// ':' { MetaSimpExpr<tag> (. /*f.addTag(std::move(tag), mod); */ .)
// }.
FnTag<Function* f> = (. Expression tag; TagModifier mod = TagModifier::NONE; .)
MetaSimpExpr<tag>
['-' TagMod<mod>] (. f->addTag(std::move(tag), mod); .).
TagMod<TagModifier& mod> =
( "assert" (. mod = TagModifier::ASSERT; .)
| "require" (. mod = TagModifier::REQUIRE; .)
).
RuleDecl<> =
"rule" tagcolon (. RuleArguments args; RuleGuards guards; DomainAnnotation typ; std::wstring arg; .)
'(' Ident<arg> tagcolon Domain<typ> (. args.add(arg, typ); .)
{',' Ident<arg> tagcolon Domain<typ> (. args.add(arg, typ); .)
} ')'
["case" RGuard<guards> {',' RGuard<guards>}]
'{' RBody<args, guards> '}' .
/* - TODO use RGuard for guards-*/
RuleContextDecl<CodeScope* scope> = (.Expression eHead, eGuards, eBody; .)
"rule" "context" tagcolon MetaSimpExpr<eHead>
"case" lparen MetaSimpExpr<eGuards> rparen
'{' MetaSimpExpr<eBody> '}' (.scope->contextRules.push_back(Expression(Operator::CONTEXT_RULE, {eHead, eGuards, eBody})); .).
Domain<DomainAnnotation& dom> =
(
"function" (. dom = DomainAnnotation::FUNCTION; .)
| "variable" (. dom = DomainAnnotation::VARIABLE; .)
).
RGuard<RuleGuards& guards>= (. Expression e; .)
MetaExpr<e> (. guards.add(std::move(e)); .).
MetaExpr<Expression& e>= (.Operator op; Expression e2; .)
MetaExpr2<e>
[MetaOp<op> MetaExpr2<e2> (. e = Expression(op, {e, e2}); .)
].
MetaExpr2<Expression& e>=
(
'(' MetaExpr<e> ')'
| MetaSimpExpr<e>
).
MetaSimpExpr<Expression& e>= (. std::wstring i1, infix; Expression e2; .)
( '-' MetaSimpExpr<e2> (. e = Expression(Operator::NEG, {e2}); .)
| IF(checkParametersList()) Ident<i1> (. e = Expression(Operator::CALL, {Expression(Atom<Identifier_t>(i1))}); .)
'(' [ MetaCalleeParams<e> ] ')'
| IF(checkInfix()) Ident<i1> Ident<infix> MetaSimpExpr<e2>
(. e = Expression(Operator::CALL, {Expression(Atom<Identifier_t>(infix))});
e.addArg(Expression(Atom<Identifier_t>(i1)));
e.addArg(std::move(e2));
.)
| Ident<i1> (. e = Expression(Operator::CALL, {Atom<Identifier_t>(i1)}); .)
).
MetaCalleeParams<Expression& e> = (. Expression e2; .)
MetaSimpExpr<e2> (. e.addArg(Expression(e2)); .)
{',' MetaSimpExpr<e2> (. e.addArg(Expression(e2)); .)
}.
RBody<const RuleArguments& args, const RuleGuards& guards> =
(. Expression e; std::wstring msg; .)
"warning" MetaExpr<e> ["message" string (. msg = t->val; .)
] (. root->add(new RuleWarning(RuleArguments(args), RuleGuards(guards), std::move(e), Atom<String_t>(msg))); .)
.
MetaOp< Operator& op> =
implic (. op = Operator::IMPL; .)
.
/*============================ Expressions ===============================*/
ExprAnnotations<Expression& e> = (. TypeAnnotation typ; std::list<Expression> tags; Expression tag; e.tags.clear();.)
Type<typ> (. e.bindType(move(typ)); .)
{';' MetaSimpExpr<tag> (. tags.push_back(tag); .)
} (. e.addTags(tags); .)
.
ExprTyped<Expression&e> = Expr<e> [tagcolon ExprAnnotations<e>].
Expr< Expression& e> (. Operator op; Expression e2; .)
= ExprArithmAdd<e>
[ RelOp<op>
ExprArithmAdd<e2> (. e = Expression(op, {e, e2}); .)
].
ExprArithmAdd< Expression& e>= (. Operator op; Expression e2; .)
ExprArithmMul< e>
[ AddOp< op>
ExprArithmAdd< e2> (. e = Expression(op, {e, e2});.)
].
ExprArithmMul< Expression& e> (. Operator op; Expression e2; .)
= ExprPostfix< e>
[ MulOp< op>
ExprArithmMul< e2> (. e = Expression(op, {e, e2}); .)
].
ExprPostfix<Expression& e>
= Term<e>
[ (. e = Expression(Operator::INDEX, {e}); .)
{lbrack CalleeParams<e> rbrack }
].
Term< Expression& e> (. std::wstring name; e = Expression(); .)
=
(IF (checkParametersList()) Ident< name>
(. e = Expression(Operator::CALL, {Atom<Identifier_t>(name)}); root->recognizeVariantConstructor(e); .)
'(' [CalleeParams<e>] ')'
| VarIdent<e> (. recognizeIdentifier(e); .)
| ListLiteral<e> (. /* tuple */.)
| StructLiteral<e> (. /* struct */.)
| LoopDecl<e>
| IfDecl<e>
| SwitchDecl<e, SWITCH_NORMAL>
| IntrinsicDecl<e>
| SequenceDecl<e>
| number (. e = Expression(Atom<Number_t>(t->val)); .)
| string (. e = Expression(Atom<String_t>(t->val)); .)
| "true" (. e = Expression(Atom<Number_t>(1)); e.bindType(TypePrimitive::Bool); .)
| "false" (. e = Expression(Atom<Number_t>(0)); e.bindType(TypePrimitive::Bool); .)
| "undef" (. e = Expression(Operator::UNDEF, {}); .)
| '-' Term<e> (. e = Expression(Operator::NEG, {e}); .)
| '(' ExprTyped<e> ')'
).
StructLiteral<Expression& e> = (. std::wstring key; Expression val; std::list<Atom<Identifier_t>> keys; size_t keyCounter=0; .)
lcurbrack
(IF(checkTokenAfterIdent(_assign)) Ident<key> '=' Expr<val>
| Expr<val> (. key = to_wstring(keyCounter++); .)
) (. keys.push_back(Atom<Identifier_t>(key)); e = Expression(Operator::LIST_NAMED, {val}); .)
{',' (IF(checkTokenAfterIdent(_assign)) Ident<key> '=' Expr<val>
| Expr<val> (. key = to_wstring(keyCounter++); .)
) (. e.addArg(Expression(val)); keys.push_back(Atom<Identifier_t>(key)); .)
} rcurbrack (. e.addBindings(keys.begin(), keys.end()); .)
.
ListLiteral<Expression& e> = (. Expression eFrom, eTo; .)
'[' (. e.setOp(Operator::LIST); .)
[ Expr<eFrom> (. e.addArg(Expression(eFrom)); .)
( ".." Expr<eTo> (. e.addArg(Expression(eTo)); e.setOp(Operator::LIST_RANGE); .)
|{',' Expr<eFrom> (. e.addArg(Expression(eFrom)); .)
}
)
]
']'.
CalleeParams<Expression& e> = (. Expression e2; .)
ExprTyped<e2> (. e.addArg(Expression(e2)); .)
{',' ExprTyped<e2> (. e.addArg(Expression(e2)); .)
}.
AddOp< Operator& op>
= (. op = Operator::ADD; .)
( '+'
| '-' (. op = Operator::SUB; .)
).
MulOp< Operator& op>
= (. op = Operator::MUL; .)
( '*'
| '/' (. op = Operator::DIV; .)
).
RelOp< Operator& op>
= (. op = Operator::EQU; .)
( equal
| (ne1 | ne2) (. op = Operator::NE; .)
| lse (. op = Operator::LSE; .)
| lss (. op = Operator::LSS; .)
| gte (. op = Operator::GTE; .)
| gtr (. op = Operator::GTR; .)
).
SkipModulesSection = "module" '{' {ANY} '}'.
END Xreate.
diff --git a/vendors/clang-codegen-private-3.8/ABIInfo.h b/vendors/clang-codegen-private-3.8/ABIInfo.h
deleted file mode 100644
index a65f270..0000000
--- a/vendors/clang-codegen-private-3.8/ABIInfo.h
+++ /dev/null
@@ -1,116 +0,0 @@
-//===----- ABIInfo.h - ABI information access & encapsulation ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_CODEGEN_ABIINFO_H
-#define LLVM_CLANG_LIB_CODEGEN_ABIINFO_H
-
-#include "clang/AST/Type.h"
-#include "llvm/IR/CallingConv.h"
-#include "llvm/IR/Type.h"
-
-namespace llvm {
- class Value;
- class LLVMContext;
- class DataLayout;
-}
-
-namespace clang {
- class ASTContext;
- class TargetInfo;
-
- namespace CodeGen {
- class ABIArgInfo;
- class Address;
- class CGCXXABI;
- class CGFunctionInfo;
- class CodeGenFunction;
- class CodeGenTypes;
- }
-
- // FIXME: All of this stuff should be part of the target interface
- // somehow. It is currently here because it is not clear how to factor
- // the targets to support this, since the Targets currently live in a
- // layer below types n'stuff.
-
-
- /// ABIInfo - Target specific hooks for defining how a type should be
- /// passed or returned from functions.
- class ABIInfo {
- public:
- CodeGen::CodeGenTypes &CGT;
- protected:
- llvm::CallingConv::ID RuntimeCC;
- llvm::CallingConv::ID BuiltinCC;
- public:
- ABIInfo(CodeGen::CodeGenTypes &cgt)
- : CGT(cgt),
- RuntimeCC(llvm::CallingConv::C),
- BuiltinCC(llvm::CallingConv::C) {}
-
- virtual ~ABIInfo();
-
- CodeGen::CGCXXABI &getCXXABI() const;
- ASTContext &getContext() const;
- llvm::LLVMContext &getVMContext() const;
- const llvm::DataLayout &getDataLayout() const;
- const TargetInfo &getTarget() const;
-
- /// Return the calling convention to use for system runtime
- /// functions.
- llvm::CallingConv::ID getRuntimeCC() const {
- return RuntimeCC;
- }
-
- /// Return the calling convention to use for compiler builtins
- llvm::CallingConv::ID getBuiltinCC() const {
- return BuiltinCC;
- }
-
- virtual void computeInfo(CodeGen::CGFunctionInfo &FI) const = 0;
-
- /// EmitVAArg - Emit the target dependent code to load a value of
- /// \arg Ty from the va_list pointed to by \arg VAListAddr.
-
- // FIXME: This is a gaping layering violation if we wanted to drop
- // the ABI information any lower than CodeGen. Of course, for
- // VAArg handling it has to be at this level; there is no way to
- // abstract this out.
- virtual CodeGen::Address EmitVAArg(CodeGen::CodeGenFunction &CGF,
- CodeGen::Address VAListAddr,
- QualType Ty) const = 0;
-
- /// Emit the target dependent code to load a value of
- /// \arg Ty from the \c __builtin_ms_va_list pointed to by \arg VAListAddr.
- virtual CodeGen::Address EmitMSVAArg(CodeGen::CodeGenFunction &CGF,
- CodeGen::Address VAListAddr,
- QualType Ty) const;
-
- virtual bool isHomogeneousAggregateBaseType(QualType Ty) const;
-
- virtual bool isHomogeneousAggregateSmallEnough(const Type *Base,
- uint64_t Members) const;
-
- virtual bool shouldSignExtUnsignedType(QualType Ty) const;
-
- bool isHomogeneousAggregate(QualType Ty, const Type *&Base,
- uint64_t &Members) const;
-
- /// A convenience method to return an indirect ABIArgInfo with an
- /// expected alignment equal to the ABI alignment of the given type.
- CodeGen::ABIArgInfo
- getNaturalAlignIndirect(QualType Ty, bool ByRef = true,
- bool Realign = false,
- llvm::Type *Padding = nullptr) const;
-
- CodeGen::ABIArgInfo
- getNaturalAlignIndirectInReg(QualType Ty, bool Realign = false) const;
- };
-} // end namespace clang
-
-#endif
diff --git a/vendors/clang-codegen-private-3.8/Address.h b/vendors/clang-codegen-private-3.8/Address.h
deleted file mode 100644
index 3343080..0000000
--- a/vendors/clang-codegen-private-3.8/Address.h
+++ /dev/null
@@ -1,118 +0,0 @@
-//===-- Address.h - An aligned address -------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This class provides a simple wrapper for a pair of a pointer and an
-// alignment.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_CODEGEN_ADDRESS_H
-#define LLVM_CLANG_LIB_CODEGEN_ADDRESS_H
-
-#include "llvm/IR/Constants.h"
-#include "clang/AST/CharUnits.h"
-
-namespace clang {
-namespace CodeGen {
-
-/// An aligned address.
-class Address {
- llvm::Value *Pointer;
- CharUnits Alignment;
-public:
- Address(llvm::Value *pointer, CharUnits alignment)
- : Pointer(pointer), Alignment(alignment) {
- assert((!alignment.isZero() || pointer == nullptr) &&
- "creating valid address with invalid alignment");
- }
-
- static Address invalid() { return Address(nullptr, CharUnits()); }
- bool isValid() const { return Pointer != nullptr; }
-
- llvm::Value *getPointer() const {
- assert(isValid());
- return Pointer;
- }
-
- /// Return the type of the pointer value.
- llvm::PointerType *getType() const {
- return llvm::cast<llvm::PointerType>(getPointer()->getType());
- }
-
- /// Return the type of the values stored in this address.
- ///
- /// When IR pointer types lose their element type, we should simply
- /// store it in Address instead for the convenience of writing code.
- llvm::Type *getElementType() const {
- return getType()->getElementType();
- }
-
- /// Return the address space that this address resides in.
- unsigned getAddressSpace() const {
- return getType()->getAddressSpace();
- }
-
- /// Return the IR name of the pointer value.
- llvm::StringRef getName() const {
- return getPointer()->getName();
- }
-
- /// Return the alignment of this pointer.
- CharUnits getAlignment() const {
- assert(isValid());
- return Alignment;
- }
-};
-
-/// A specialization of Address that requires the address to be an
-/// LLVM Constant.
-class ConstantAddress : public Address {
-public:
- ConstantAddress(llvm::Constant *pointer, CharUnits alignment)
- : Address(pointer, alignment) {}
-
- static ConstantAddress invalid() {
- return ConstantAddress(nullptr, CharUnits());
- }
-
- llvm::Constant *getPointer() const {
- return llvm::cast<llvm::Constant>(Address::getPointer());
- }
-
- ConstantAddress getBitCast(llvm::Type *ty) const {
- return ConstantAddress(llvm::ConstantExpr::getBitCast(getPointer(), ty),
- getAlignment());
- }
-
- ConstantAddress getElementBitCast(llvm::Type *ty) const {
- return getBitCast(ty->getPointerTo(getAddressSpace()));
- }
-
- static bool isaImpl(Address addr) {
- return llvm::isa<llvm::Constant>(addr.getPointer());
- }
- static ConstantAddress castImpl(Address addr) {
- return ConstantAddress(llvm::cast<llvm::Constant>(addr.getPointer()),
- addr.getAlignment());
- }
-};
-
-}
-
-// Present a minimal LLVM-like casting interface.
-template <class U> inline U cast(CodeGen::Address addr) {
- return U::castImpl(addr);
-}
-template <class U> inline bool isa(CodeGen::Address addr) {
- return U::isaImpl(addr);
-}
-
-}
-
-#endif
diff --git a/vendors/clang-codegen-private-3.8/CGCall.h b/vendors/clang-codegen-private-3.8/CGCall.h
deleted file mode 100644
index 2ebd09b..0000000
--- a/vendors/clang-codegen-private-3.8/CGCall.h
+++ /dev/null
@@ -1,178 +0,0 @@
-//===----- CGCall.h - Encapsulate calling convention details ----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// These classes wrap the information about a call or function
-// definition used to handle ABI compliancy.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_CODEGEN_CGCALL_H
-#define LLVM_CLANG_LIB_CODEGEN_CGCALL_H
-
-#include "CGValue.h"
-#include "EHScopeStack.h"
-#include "clang/AST/CanonicalType.h"
-#include "clang/AST/Type.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/IR/Value.h"
-
-// FIXME: Restructure so we don't have to expose so much stuff.
-#include "ABIInfo.h"
-
-namespace llvm {
- class AttributeSet;
- class Function;
- class Type;
- class Value;
-}
-
-namespace clang {
- class ASTContext;
- class Decl;
- class FunctionDecl;
- class ObjCMethodDecl;
- class VarDecl;
-
-namespace CodeGen {
- typedef SmallVector<llvm::AttributeSet, 8> AttributeListType;
-
- struct CallArg {
- RValue RV;
- QualType Ty;
- bool NeedsCopy;
- CallArg(RValue rv, QualType ty, bool needscopy)
- : RV(rv), Ty(ty), NeedsCopy(needscopy)
- { }
- };
-
- /// CallArgList - Type for representing both the value and type of
- /// arguments in a call.
- class CallArgList :
- public SmallVector<CallArg, 16> {
- public:
- CallArgList() : StackBase(nullptr) {}
-
- struct Writeback {
- /// The original argument. Note that the argument l-value
- /// is potentially null.
- LValue Source;
-
- /// The temporary alloca.
- Address Temporary;
-
- /// A value to "use" after the writeback, or null.
- llvm::Value *ToUse;
- };
-
- struct CallArgCleanup {
- EHScopeStack::stable_iterator Cleanup;
-
- /// The "is active" insertion point. This instruction is temporary and
- /// will be removed after insertion.
- llvm::Instruction *IsActiveIP;
- };
-
- void add(RValue rvalue, QualType type, bool needscopy = false) {
- push_back(CallArg(rvalue, type, needscopy));
- }
-
- void addFrom(const CallArgList &other) {
- insert(end(), other.begin(), other.end());
- Writebacks.insert(Writebacks.end(),
- other.Writebacks.begin(), other.Writebacks.end());
- }
-
- void addWriteback(LValue srcLV, Address temporary,
- llvm::Value *toUse) {
- Writeback writeback = { srcLV, temporary, toUse };
- Writebacks.push_back(writeback);
- }
-
- bool hasWritebacks() const { return !Writebacks.empty(); }
-
- typedef llvm::iterator_range<SmallVectorImpl<Writeback>::const_iterator>
- writeback_const_range;
-
- writeback_const_range writebacks() const {
- return writeback_const_range(Writebacks.begin(), Writebacks.end());
- }
-
- void addArgCleanupDeactivation(EHScopeStack::stable_iterator Cleanup,
- llvm::Instruction *IsActiveIP) {
- CallArgCleanup ArgCleanup;
- ArgCleanup.Cleanup = Cleanup;
- ArgCleanup.IsActiveIP = IsActiveIP;
- CleanupsToDeactivate.push_back(ArgCleanup);
- }
-
- ArrayRef<CallArgCleanup> getCleanupsToDeactivate() const {
- return CleanupsToDeactivate;
- }
-
- void allocateArgumentMemory(CodeGenFunction &CGF);
- llvm::Instruction *getStackBase() const { return StackBase; }
- void freeArgumentMemory(CodeGenFunction &CGF) const;
-
- /// \brief Returns if we're using an inalloca struct to pass arguments in
- /// memory.
- bool isUsingInAlloca() const { return StackBase; }
-
- private:
- SmallVector<Writeback, 1> Writebacks;
-
- /// Deactivate these cleanups immediately before making the call. This
- /// is used to cleanup objects that are owned by the callee once the call
- /// occurs.
- SmallVector<CallArgCleanup, 1> CleanupsToDeactivate;
-
- /// The stacksave call. It dominates all of the argument evaluation.
- llvm::CallInst *StackBase;
-
- /// The iterator pointing to the stack restore cleanup. We manually run and
- /// deactivate this cleanup after the call in the unexceptional case because
- /// it doesn't run in the normal order.
- EHScopeStack::stable_iterator StackCleanup;
- };
-
- /// FunctionArgList - Type for representing both the decl and type
- /// of parameters to a function. The decl must be either a
- /// ParmVarDecl or ImplicitParamDecl.
- class FunctionArgList : public SmallVector<const VarDecl*, 16> {
- };
-
- /// ReturnValueSlot - Contains the address where the return value of a
- /// function can be stored, and whether the address is volatile or not.
- class ReturnValueSlot {
- llvm::PointerIntPair<llvm::Value *, 2, unsigned int> Value;
- CharUnits Alignment;
-
- // Return value slot flags
- enum Flags {
- IS_VOLATILE = 0x1,
- IS_UNUSED = 0x2,
- };
-
- public:
- ReturnValueSlot() {}
- ReturnValueSlot(Address Addr, bool IsVolatile, bool IsUnused = false)
- : Value(Addr.isValid() ? Addr.getPointer() : nullptr,
- (IsVolatile ? IS_VOLATILE : 0) | (IsUnused ? IS_UNUSED : 0)),
- Alignment(Addr.isValid() ? Addr.getAlignment() : CharUnits::Zero()) {}
-
- bool isNull() const { return !getValue().isValid(); }
-
- bool isVolatile() const { return Value.getInt() & IS_VOLATILE; }
- Address getValue() const { return Address(Value.getPointer(), Alignment); }
- bool isUnused() const { return Value.getInt() & IS_UNUSED; }
- };
-
-} // end namespace CodeGen
-} // end namespace clang
-
-#endif
diff --git a/vendors/clang-codegen-private-3.8/CGVTables.h b/vendors/clang-codegen-private-3.8/CGVTables.h
deleted file mode 100644
index c27e54a..0000000
--- a/vendors/clang-codegen-private-3.8/CGVTables.h
+++ /dev/null
@@ -1,119 +0,0 @@
-//===--- CGVTables.h - Emit LLVM Code for C++ vtables -----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This contains code dealing with C++ code generation of virtual tables.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_CODEGEN_CGVTABLES_H
-#define LLVM_CLANG_LIB_CODEGEN_CGVTABLES_H
-
-#include "clang/AST/BaseSubobject.h"
-#include "clang/AST/CharUnits.h"
-#include "clang/AST/GlobalDecl.h"
-#include "clang/AST/VTableBuilder.h"
-#include "clang/Basic/ABI.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/IR/GlobalVariable.h"
-
-namespace clang {
- class CXXRecordDecl;
-
-namespace CodeGen {
- class CodeGenModule;
-
-class CodeGenVTables {
- CodeGenModule &CGM;
-
- VTableContextBase *VTContext;
-
- /// VTableAddressPointsMapTy - Address points for a single vtable.
- typedef llvm::DenseMap<BaseSubobject, uint64_t> VTableAddressPointsMapTy;
-
- typedef std::pair<const CXXRecordDecl *, BaseSubobject> BaseSubobjectPairTy;
- typedef llvm::DenseMap<BaseSubobjectPairTy, uint64_t> SubVTTIndiciesMapTy;
-
- /// SubVTTIndicies - Contains indices into the various sub-VTTs.
- SubVTTIndiciesMapTy SubVTTIndicies;
-
- typedef llvm::DenseMap<BaseSubobjectPairTy, uint64_t>
- SecondaryVirtualPointerIndicesMapTy;
-
- /// SecondaryVirtualPointerIndices - Contains the secondary virtual pointer
- /// indices.
- SecondaryVirtualPointerIndicesMapTy SecondaryVirtualPointerIndices;
-
- /// emitThunk - Emit a single thunk.
- void emitThunk(GlobalDecl GD, const ThunkInfo &Thunk, bool ForVTable);
-
- /// maybeEmitThunkForVTable - Emit the given thunk for the vtable if needed by
- /// the ABI.
- void maybeEmitThunkForVTable(GlobalDecl GD, const ThunkInfo &Thunk);
-
-public:
- /// CreateVTableInitializer - Create a vtable initializer for the given record
- /// decl.
- /// \param Components - The vtable components; this is really an array of
- /// VTableComponents.
- llvm::Constant *CreateVTableInitializer(
- const CXXRecordDecl *RD, const VTableComponent *Components,
- unsigned NumComponents, const VTableLayout::VTableThunkTy *VTableThunks,
- unsigned NumVTableThunks, llvm::Constant *RTTI);
-
- CodeGenVTables(CodeGenModule &CGM);
-
- ItaniumVTableContext &getItaniumVTableContext() {
- return *cast<ItaniumVTableContext>(VTContext);
- }
-
- MicrosoftVTableContext &getMicrosoftVTableContext() {
- return *cast<MicrosoftVTableContext>(VTContext);
- }
-
- /// getSubVTTIndex - Return the index of the sub-VTT for the base class of the
- /// given record decl.
- uint64_t getSubVTTIndex(const CXXRecordDecl *RD, BaseSubobject Base);
-
- /// getSecondaryVirtualPointerIndex - Return the index in the VTT where the
- /// virtual pointer for the given subobject is located.
- uint64_t getSecondaryVirtualPointerIndex(const CXXRecordDecl *RD,
- BaseSubobject Base);
-
- /// GenerateConstructionVTable - Generate a construction vtable for the given
- /// base subobject.
- llvm::GlobalVariable *
- GenerateConstructionVTable(const CXXRecordDecl *RD, const BaseSubobject &Base,
- bool BaseIsVirtual,
- llvm::GlobalVariable::LinkageTypes Linkage,
- VTableAddressPointsMapTy& AddressPoints);
-
-
- /// GetAddrOfVTT - Get the address of the VTT for the given record decl.
- llvm::GlobalVariable *GetAddrOfVTT(const CXXRecordDecl *RD);
-
- /// EmitVTTDefinition - Emit the definition of the given vtable.
- void EmitVTTDefinition(llvm::GlobalVariable *VTT,
- llvm::GlobalVariable::LinkageTypes Linkage,
- const CXXRecordDecl *RD);
-
- /// EmitThunks - Emit the associated thunks for the given global decl.
- void EmitThunks(GlobalDecl GD);
-
- /// GenerateClassData - Generate all the class data required to be
- /// generated upon definition of a KeyFunction. This includes the
- /// vtable, the RTTI data structure (if RTTI is enabled) and the VTT
- /// (if the class has virtual bases).
- void GenerateClassData(const CXXRecordDecl *RD);
-
- bool isVTableExternal(const CXXRecordDecl *RD);
-};
-
-} // end namespace CodeGen
-} // end namespace clang
-#endif
diff --git a/vendors/clang-codegen-private-3.8/CGValue.h b/vendors/clang-codegen-private-3.8/CGValue.h
deleted file mode 100644
index 3ccc4cd..0000000
--- a/vendors/clang-codegen-private-3.8/CGValue.h
+++ /dev/null
@@ -1,595 +0,0 @@
-//===-- CGValue.h - LLVM CodeGen wrappers for llvm::Value* ------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// These classes implement wrappers around llvm::Value in order to
-// fully represent the range of values for C L- and R- values.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_CODEGEN_CGVALUE_H
-#define LLVM_CLANG_LIB_CODEGEN_CGVALUE_H
-
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Type.h"
-#include "llvm/IR/Value.h"
-#include "llvm/IR/Type.h"
-#include "Address.h"
-
-namespace llvm {
- class Constant;
- class MDNode;
-}
-
-namespace clang {
-namespace CodeGen {
- class AggValueSlot;
- struct CGBitFieldInfo;
-
-/// RValue - This trivial value class is used to represent the result of an
-/// expression that is evaluated. It can be one of three things: either a
-/// simple LLVM SSA value, a pair of SSA values for complex numbers, or the
-/// address of an aggregate value in memory.
-class RValue {
- enum Flavor { Scalar, Complex, Aggregate };
-
- // The shift to make to an aggregate's alignment to make it look
- // like a pointer.
- enum { AggAlignShift = 4 };
-
- // Stores first value and flavor.
- llvm::PointerIntPair<llvm::Value *, 2, Flavor> V1;
- // Stores second value and volatility.
- llvm::PointerIntPair<llvm::Value *, 1, bool> V2;
-
-public:
- bool isScalar() const { return V1.getInt() == Scalar; }
- bool isComplex() const { return V1.getInt() == Complex; }
- bool isAggregate() const { return V1.getInt() == Aggregate; }
-
- bool isVolatileQualified() const { return V2.getInt(); }
-
- /// getScalarVal() - Return the Value* of this scalar value.
- llvm::Value *getScalarVal() const {
- assert(isScalar() && "Not a scalar!");
- return V1.getPointer();
- }
-
- /// getComplexVal - Return the real/imag components of this complex value.
- ///
- std::pair<llvm::Value *, llvm::Value *> getComplexVal() const {
- return std::make_pair(V1.getPointer(), V2.getPointer());
- }
-
- /// getAggregateAddr() - Return the Value* of the address of the aggregate.
- Address getAggregateAddress() const {
- assert(isAggregate() && "Not an aggregate!");
- auto align = reinterpret_cast<uintptr_t>(V2.getPointer()) >> AggAlignShift;
- return Address(V1.getPointer(), CharUnits::fromQuantity(align));
- }
- llvm::Value *getAggregatePointer() const {
- assert(isAggregate() && "Not an aggregate!");
- return V1.getPointer();
- }
-
- static RValue getIgnored() {
- // FIXME: should we make this a more explicit state?
- return get(nullptr);
- }
-
- static RValue get(llvm::Value *V) {
- RValue ER;
- ER.V1.setPointer(V);
- ER.V1.setInt(Scalar);
- ER.V2.setInt(false);
- return ER;
- }
- static RValue getComplex(llvm::Value *V1, llvm::Value *V2) {
- RValue ER;
- ER.V1.setPointer(V1);
- ER.V2.setPointer(V2);
- ER.V1.setInt(Complex);
- ER.V2.setInt(false);
- return ER;
- }
- static RValue getComplex(const std::pair<llvm::Value *, llvm::Value *> &C) {
- return getComplex(C.first, C.second);
- }
- // FIXME: Aggregate rvalues need to retain information about whether they are
- // volatile or not. Remove default to find all places that probably get this
- // wrong.
- static RValue getAggregate(Address addr, bool isVolatile = false) {
- RValue ER;
- ER.V1.setPointer(addr.getPointer());
- ER.V1.setInt(Aggregate);
-
- auto align = static_cast<uintptr_t>(addr.getAlignment().getQuantity());
- ER.V2.setPointer(reinterpret_cast<llvm::Value*>(align << AggAlignShift));
- ER.V2.setInt(isVolatile);
- return ER;
- }
-};
-
-/// Does an ARC strong l-value have precise lifetime?
-enum ARCPreciseLifetime_t {
- ARCImpreciseLifetime, ARCPreciseLifetime
-};
-
-/// The source of the alignment of an l-value; an expression of
-/// confidence in the alignment actually matching the estimate.
-enum class AlignmentSource {
- /// The l-value was an access to a declared entity or something
- /// equivalently strong, like the address of an array allocated by a
- /// language runtime.
- Decl,
-
- /// The l-value was considered opaque, so the alignment was
- /// determined from a type, but that type was an explicitly-aligned
- /// typedef.
- AttributedType,
-
- /// The l-value was considered opaque, so the alignment was
- /// determined from a type.
- Type
-};
-
-/// Given that the base address has the given alignment source, what's
-/// our confidence in the alignment of the field?
-static inline AlignmentSource getFieldAlignmentSource(AlignmentSource Source) {
- // For now, we don't distinguish fields of opaque pointers from
- // top-level declarations, but maybe we should.
- return AlignmentSource::Decl;
-}
-
-/// LValue - This represents an lvalue references. Because C/C++ allow
-/// bitfields, this is not a simple LLVM pointer, it may be a pointer plus a
-/// bitrange.
-class LValue {
- enum {
- Simple, // This is a normal l-value, use getAddress().
- VectorElt, // This is a vector element l-value (V[i]), use getVector*
- BitField, // This is a bitfield l-value, use getBitfield*.
- ExtVectorElt, // This is an extended vector subset, use getExtVectorComp
- GlobalReg // This is a register l-value, use getGlobalReg()
- } LVType;
-
- llvm::Value *V;
-
- union {
- // Index into a vector subscript: V[i]
- llvm::Value *VectorIdx;
-
- // ExtVector element subset: V.xyx
- llvm::Constant *VectorElts;
-
- // BitField start bit and size
- const CGBitFieldInfo *BitFieldInfo;
- };
-
- QualType Type;
-
- // 'const' is unused here
- Qualifiers Quals;
-
- // The alignment to use when accessing this lvalue. (For vector elements,
- // this is the alignment of the whole vector.)
- int64_t Alignment;
-
- // objective-c's ivar
- bool Ivar:1;
-
- // objective-c's ivar is an array
- bool ObjIsArray:1;
-
- // LValue is non-gc'able for any reason, including being a parameter or local
- // variable.
- bool NonGC: 1;
-
- // Lvalue is a global reference of an objective-c object
- bool GlobalObjCRef : 1;
-
- // Lvalue is a thread local reference
- bool ThreadLocalRef : 1;
-
- // Lvalue has ARC imprecise lifetime. We store this inverted to try
- // to make the default bitfield pattern all-zeroes.
- bool ImpreciseLifetime : 1;
-
- unsigned AlignSource : 2;
-
- // This flag shows if a nontemporal load/stores should be used when accessing
- // this lvalue.
- bool Nontemporal : 1;
-
- Expr *BaseIvarExp;
-
- /// Used by struct-path-aware TBAA.
- QualType TBAABaseType;
- /// Offset relative to the base type.
- uint64_t TBAAOffset;
-
- /// TBAAInfo - TBAA information to attach to dereferences of this LValue.
- llvm::MDNode *TBAAInfo;
-
-private:
- void Initialize(QualType Type, Qualifiers Quals,
- CharUnits Alignment, AlignmentSource AlignSource,
- llvm::MDNode *TBAAInfo = nullptr) {
- assert((!Alignment.isZero() || Type->isIncompleteType()) &&
- "initializing l-value with zero alignment!");
- this->Type = Type;
- this->Quals = Quals;
- this->Alignment = Alignment.getQuantity();
- assert(this->Alignment == Alignment.getQuantity() &&
- "Alignment exceeds allowed max!");
- this->AlignSource = unsigned(AlignSource);
-
- // Initialize Objective-C flags.
- this->Ivar = this->ObjIsArray = this->NonGC = this->GlobalObjCRef = false;
- this->ImpreciseLifetime = false;
- this->Nontemporal = false;
- this->ThreadLocalRef = false;
- this->BaseIvarExp = nullptr;
-
- // Initialize fields for TBAA.
- this->TBAABaseType = Type;
- this->TBAAOffset = 0;
- this->TBAAInfo = TBAAInfo;
- }
-
-public:
- bool isSimple() const { return LVType == Simple; }
- bool isVectorElt() const { return LVType == VectorElt; }
- bool isBitField() const { return LVType == BitField; }
- bool isExtVectorElt() const { return LVType == ExtVectorElt; }
- bool isGlobalReg() const { return LVType == GlobalReg; }
-
- bool isVolatileQualified() const { return Quals.hasVolatile(); }
- bool isRestrictQualified() const { return Quals.hasRestrict(); }
- unsigned getVRQualifiers() const {
- return Quals.getCVRQualifiers() & ~Qualifiers::Const;
- }
-
- QualType getType() const { return Type; }
-
- Qualifiers::ObjCLifetime getObjCLifetime() const {
- return Quals.getObjCLifetime();
- }
-
- bool isObjCIvar() const { return Ivar; }
- void setObjCIvar(bool Value) { Ivar = Value; }
-
- bool isObjCArray() const { return ObjIsArray; }
- void setObjCArray(bool Value) { ObjIsArray = Value; }
-
- bool isNonGC () const { return NonGC; }
- void setNonGC(bool Value) { NonGC = Value; }
-
- bool isGlobalObjCRef() const { return GlobalObjCRef; }
- void setGlobalObjCRef(bool Value) { GlobalObjCRef = Value; }
-
- bool isThreadLocalRef() const { return ThreadLocalRef; }
- void setThreadLocalRef(bool Value) { ThreadLocalRef = Value;}
-
- ARCPreciseLifetime_t isARCPreciseLifetime() const {
- return ARCPreciseLifetime_t(!ImpreciseLifetime);
- }
- void setARCPreciseLifetime(ARCPreciseLifetime_t value) {
- ImpreciseLifetime = (value == ARCImpreciseLifetime);
- }
- bool isNontemporal() const { return Nontemporal; }
- void setNontemporal(bool Value) { Nontemporal = Value; }
-
- bool isObjCWeak() const {
- return Quals.getObjCGCAttr() == Qualifiers::Weak;
- }
- bool isObjCStrong() const {
- return Quals.getObjCGCAttr() == Qualifiers::Strong;
- }
-
- bool isVolatile() const {
- return Quals.hasVolatile();
- }
-
- Expr *getBaseIvarExp() const { return BaseIvarExp; }
- void setBaseIvarExp(Expr *V) { BaseIvarExp = V; }
-
- QualType getTBAABaseType() const { return TBAABaseType; }
- void setTBAABaseType(QualType T) { TBAABaseType = T; }
-
- uint64_t getTBAAOffset() const { return TBAAOffset; }
- void setTBAAOffset(uint64_t O) { TBAAOffset = O; }
-
- llvm::MDNode *getTBAAInfo() const { return TBAAInfo; }
- void setTBAAInfo(llvm::MDNode *N) { TBAAInfo = N; }
-
- const Qualifiers &getQuals() const { return Quals; }
- Qualifiers &getQuals() { return Quals; }
-
- unsigned getAddressSpace() const { return Quals.getAddressSpace(); }
-
- CharUnits getAlignment() const { return CharUnits::fromQuantity(Alignment); }
- void setAlignment(CharUnits A) { Alignment = A.getQuantity(); }
-
- AlignmentSource getAlignmentSource() const {
- return AlignmentSource(AlignSource);
- }
- void setAlignmentSource(AlignmentSource Source) {
- AlignSource = unsigned(Source);
- }
-
- // simple lvalue
- llvm::Value *getPointer() const {
- assert(isSimple());
- return V;
- }
- Address getAddress() const { return Address(getPointer(), getAlignment()); }
- void setAddress(Address address) {
- assert(isSimple());
- V = address.getPointer();
- Alignment = address.getAlignment().getQuantity();
- }
-
- // vector elt lvalue
- Address getVectorAddress() const {
- return Address(getVectorPointer(), getAlignment());
- }
- llvm::Value *getVectorPointer() const { assert(isVectorElt()); return V; }
- llvm::Value *getVectorIdx() const { assert(isVectorElt()); return VectorIdx; }
-
- // extended vector elements.
- Address getExtVectorAddress() const {
- return Address(getExtVectorPointer(), getAlignment());
- }
- llvm::Value *getExtVectorPointer() const {
- assert(isExtVectorElt());
- return V;
- }
- llvm::Constant *getExtVectorElts() const {
- assert(isExtVectorElt());
- return VectorElts;
- }
-
- // bitfield lvalue
- Address getBitFieldAddress() const {
- return Address(getBitFieldPointer(), getAlignment());
- }
- llvm::Value *getBitFieldPointer() const { assert(isBitField()); return V; }
- const CGBitFieldInfo &getBitFieldInfo() const {
- assert(isBitField());
- return *BitFieldInfo;
- }
-
- // global register lvalue
- llvm::Value *getGlobalReg() const { assert(isGlobalReg()); return V; }
-
- static LValue MakeAddr(Address address, QualType type,
- ASTContext &Context,
- AlignmentSource alignSource,
- llvm::MDNode *TBAAInfo = nullptr) {
- Qualifiers qs = type.getQualifiers();
- qs.setObjCGCAttr(Context.getObjCGCAttrKind(type));
-
- LValue R;
- R.LVType = Simple;
- assert(address.getPointer()->getType()->isPointerTy());
- R.V = address.getPointer();
- R.Initialize(type, qs, address.getAlignment(), alignSource, TBAAInfo);
- return R;
- }
-
- static LValue MakeVectorElt(Address vecAddress, llvm::Value *Idx,
- QualType type, AlignmentSource alignSource) {
- LValue R;
- R.LVType = VectorElt;
- R.V = vecAddress.getPointer();
- R.VectorIdx = Idx;
- R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(),
- alignSource);
- return R;
- }
-
- static LValue MakeExtVectorElt(Address vecAddress, llvm::Constant *Elts,
- QualType type, AlignmentSource alignSource) {
- LValue R;
- R.LVType = ExtVectorElt;
- R.V = vecAddress.getPointer();
- R.VectorElts = Elts;
- R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(),
- alignSource);
- return R;
- }
-
- /// \brief Create a new object to represent a bit-field access.
- ///
- /// \param Addr - The base address of the bit-field sequence this
- /// bit-field refers to.
- /// \param Info - The information describing how to perform the bit-field
- /// access.
- static LValue MakeBitfield(Address Addr,
- const CGBitFieldInfo &Info,
- QualType type,
- AlignmentSource alignSource) {
- LValue R;
- R.LVType = BitField;
- R.V = Addr.getPointer();
- R.BitFieldInfo = &Info;
- R.Initialize(type, type.getQualifiers(), Addr.getAlignment(), alignSource);
- return R;
- }
-
- static LValue MakeGlobalReg(Address Reg, QualType type) {
- LValue R;
- R.LVType = GlobalReg;
- R.V = Reg.getPointer();
- R.Initialize(type, type.getQualifiers(), Reg.getAlignment(),
- AlignmentSource::Decl);
- return R;
- }
-
- RValue asAggregateRValue() const {
- return RValue::getAggregate(getAddress(), isVolatileQualified());
- }
-};
-
-/// An aggregate value slot.
-class AggValueSlot {
- /// The address.
- llvm::Value *Addr;
-
- // Qualifiers
- Qualifiers Quals;
-
- unsigned short Alignment;
-
- /// DestructedFlag - This is set to true if some external code is
- /// responsible for setting up a destructor for the slot. Otherwise
- /// the code which constructs it should push the appropriate cleanup.
- bool DestructedFlag : 1;
-
- /// ObjCGCFlag - This is set to true if writing to the memory in the
- /// slot might require calling an appropriate Objective-C GC
- /// barrier. The exact interaction here is unnecessarily mysterious.
- bool ObjCGCFlag : 1;
-
- /// ZeroedFlag - This is set to true if the memory in the slot is
- /// known to be zero before the assignment into it. This means that
- /// zero fields don't need to be set.
- bool ZeroedFlag : 1;
-
- /// AliasedFlag - This is set to true if the slot might be aliased
- /// and it's not undefined behavior to access it through such an
- /// alias. Note that it's always undefined behavior to access a C++
- /// object that's under construction through an alias derived from
- /// outside the construction process.
- ///
- /// This flag controls whether calls that produce the aggregate
- /// value may be evaluated directly into the slot, or whether they
- /// must be evaluated into an unaliased temporary and then memcpy'ed
- /// over. Since it's invalid in general to memcpy a non-POD C++
- /// object, it's important that this flag never be set when
- /// evaluating an expression which constructs such an object.
- bool AliasedFlag : 1;
-
-public:
- enum IsAliased_t { IsNotAliased, IsAliased };
- enum IsDestructed_t { IsNotDestructed, IsDestructed };
- enum IsZeroed_t { IsNotZeroed, IsZeroed };
- enum NeedsGCBarriers_t { DoesNotNeedGCBarriers, NeedsGCBarriers };
-
- /// ignored - Returns an aggregate value slot indicating that the
- /// aggregate value is being ignored.
- static AggValueSlot ignored() {
- return forAddr(Address::invalid(), Qualifiers(), IsNotDestructed,
- DoesNotNeedGCBarriers, IsNotAliased);
- }
-
- /// forAddr - Make a slot for an aggregate value.
- ///
- /// \param quals - The qualifiers that dictate how the slot should
- /// be initialied. Only 'volatile' and the Objective-C lifetime
- /// qualifiers matter.
- ///
- /// \param isDestructed - true if something else is responsible
- /// for calling destructors on this object
- /// \param needsGC - true if the slot is potentially located
- /// somewhere that ObjC GC calls should be emitted for
- static AggValueSlot forAddr(Address addr,
- Qualifiers quals,
- IsDestructed_t isDestructed,
- NeedsGCBarriers_t needsGC,
- IsAliased_t isAliased,
- IsZeroed_t isZeroed = IsNotZeroed) {
- AggValueSlot AV;
- if (addr.isValid()) {
- AV.Addr = addr.getPointer();
- AV.Alignment = addr.getAlignment().getQuantity();
- } else {
- AV.Addr = nullptr;
- AV.Alignment = 0;
- }
- AV.Quals = quals;
- AV.DestructedFlag = isDestructed;
- AV.ObjCGCFlag = needsGC;
- AV.ZeroedFlag = isZeroed;
- AV.AliasedFlag = isAliased;
- return AV;
- }
-
- static AggValueSlot forLValue(const LValue &LV,
- IsDestructed_t isDestructed,
- NeedsGCBarriers_t needsGC,
- IsAliased_t isAliased,
- IsZeroed_t isZeroed = IsNotZeroed) {
- return forAddr(LV.getAddress(),
- LV.getQuals(), isDestructed, needsGC, isAliased, isZeroed);
- }
-
- IsDestructed_t isExternallyDestructed() const {
- return IsDestructed_t(DestructedFlag);
- }
- void setExternallyDestructed(bool destructed = true) {
- DestructedFlag = destructed;
- }
-
- Qualifiers getQualifiers() const { return Quals; }
-
- bool isVolatile() const {
- return Quals.hasVolatile();
- }
-
- void setVolatile(bool flag) {
- Quals.setVolatile(flag);
- }
-
- Qualifiers::ObjCLifetime getObjCLifetime() const {
- return Quals.getObjCLifetime();
- }
-
- NeedsGCBarriers_t requiresGCollection() const {
- return NeedsGCBarriers_t(ObjCGCFlag);
- }
-
- llvm::Value *getPointer() const {
- return Addr;
- }
-
- Address getAddress() const {
- return Address(Addr, getAlignment());
- }
-
- bool isIgnored() const {
- return Addr == nullptr;
- }
-
- CharUnits getAlignment() const {
- return CharUnits::fromQuantity(Alignment);
- }
-
- IsAliased_t isPotentiallyAliased() const {
- return IsAliased_t(AliasedFlag);
- }
-
- RValue asRValue() const {
- if (isIgnored()) {
- return RValue::getIgnored();
- } else {
- return RValue::getAggregate(getAddress(), isVolatile());
- }
- }
-
- void setZeroed(bool V = true) { ZeroedFlag = V; }
- IsZeroed_t isZeroed() const {
- return IsZeroed_t(ZeroedFlag);
- }
-};
-
-} // end namespace CodeGen
-} // end namespace clang
-
-#endif
diff --git a/vendors/clang-codegen-private-3.8/CodeGenModule.h b/vendors/clang-codegen-private-3.8/CodeGenModule.h
deleted file mode 100644
index fdb4d78..0000000
--- a/vendors/clang-codegen-private-3.8/CodeGenModule.h
+++ /dev/null
@@ -1,1245 +0,0 @@
-//===--- CodeGenModule.h - Per-Module state for LLVM CodeGen ----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This is the internal per-translation-unit state used for llvm translation.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_CODEGEN_CODEGENMODULE_H
-#define LLVM_CLANG_LIB_CODEGEN_CODEGENMODULE_H
-
-#include "CGVTables.h"
-#include "CodeGenTypeCache.h"
-#include "CodeGenTypes.h"
-#include "SanitizerMetadata.h"
-#include "clang/AST/Attr.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/GlobalDecl.h"
-#include "clang/AST/Mangle.h"
-#include "clang/Basic/ABI.h"
-#include "clang/Basic/LangOptions.h"
-#include "clang/Basic/Module.h"
-#include "clang/Basic/SanitizerBlacklist.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SetVector.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/IR/Module.h"
-#include "llvm/IR/ValueHandle.h"
-
-namespace llvm {
-class Module;
-class Constant;
-class ConstantInt;
-class Function;
-class GlobalValue;
-class DataLayout;
-class FunctionType;
-class LLVMContext;
-class IndexedInstrProfReader;
-}
-
-namespace clang {
-class TargetCodeGenInfo;
-class ASTContext;
-class AtomicType;
-class FunctionDecl;
-class IdentifierInfo;
-class ObjCMethodDecl;
-class ObjCImplementationDecl;
-class ObjCCategoryImplDecl;
-class ObjCProtocolDecl;
-class ObjCEncodeExpr;
-class BlockExpr;
-class CharUnits;
-class Decl;
-class Expr;
-class Stmt;
-class InitListExpr;
-class StringLiteral;
-class NamedDecl;
-class ValueDecl;
-class VarDecl;
-class LangOptions;
-class CodeGenOptions;
-class HeaderSearchOptions;
-class PreprocessorOptions;
-class DiagnosticsEngine;
-class AnnotateAttr;
-class CXXDestructorDecl;
-class Module;
-class CoverageSourceInfo;
-
-namespace CodeGen {
-
-class CallArgList;
-class CodeGenFunction;
-class CodeGenTBAA;
-class CGCXXABI;
-class CGDebugInfo;
-class CGObjCRuntime;
-class CGOpenCLRuntime;
-class CGOpenMPRuntime;
-class CGCUDARuntime;
-class BlockFieldFlags;
-class FunctionArgList;
-class CoverageMappingModuleGen;
-
-struct OrderGlobalInits {
- unsigned int priority;
- unsigned int lex_order;
- OrderGlobalInits(unsigned int p, unsigned int l)
- : priority(p), lex_order(l) {}
-
- bool operator==(const OrderGlobalInits &RHS) const {
- return priority == RHS.priority && lex_order == RHS.lex_order;
- }
-
- bool operator<(const OrderGlobalInits &RHS) const {
- return std::tie(priority, lex_order) <
- std::tie(RHS.priority, RHS.lex_order);
- }
-};
-
-struct ObjCEntrypoints {
- ObjCEntrypoints() { memset(this, 0, sizeof(*this)); }
-
- /// void objc_autoreleasePoolPop(void*);
- llvm::Constant *objc_autoreleasePoolPop;
-
- /// void *objc_autoreleasePoolPush(void);
- llvm::Constant *objc_autoreleasePoolPush;
-
- /// id objc_autorelease(id);
- llvm::Constant *objc_autorelease;
-
- /// id objc_autoreleaseReturnValue(id);
- llvm::Constant *objc_autoreleaseReturnValue;
-
- /// void objc_copyWeak(id *dest, id *src);
- llvm::Constant *objc_copyWeak;
-
- /// void objc_destroyWeak(id*);
- llvm::Constant *objc_destroyWeak;
-
- /// id objc_initWeak(id*, id);
- llvm::Constant *objc_initWeak;
-
- /// id objc_loadWeak(id*);
- llvm::Constant *objc_loadWeak;
-
- /// id objc_loadWeakRetained(id*);
- llvm::Constant *objc_loadWeakRetained;
-
- /// void objc_moveWeak(id *dest, id *src);
- llvm::Constant *objc_moveWeak;
-
- /// id objc_retain(id);
- llvm::Constant *objc_retain;
-
- /// id objc_retainAutorelease(id);
- llvm::Constant *objc_retainAutorelease;
-
- /// id objc_retainAutoreleaseReturnValue(id);
- llvm::Constant *objc_retainAutoreleaseReturnValue;
-
- /// id objc_retainAutoreleasedReturnValue(id);
- llvm::Constant *objc_retainAutoreleasedReturnValue;
-
- /// id objc_retainBlock(id);
- llvm::Constant *objc_retainBlock;
-
- /// void objc_release(id);
- llvm::Constant *objc_release;
-
- /// id objc_storeStrong(id*, id);
- llvm::Constant *objc_storeStrong;
-
- /// id objc_storeWeak(id*, id);
- llvm::Constant *objc_storeWeak;
-
- /// A void(void) inline asm to use to mark that the return value of
- /// a call will be immediately retain.
- llvm::InlineAsm *retainAutoreleasedReturnValueMarker;
-
- /// void clang.arc.use(...);
- llvm::Constant *clang_arc_use;
-};
-
-/// This class records statistics on instrumentation based profiling.
-class InstrProfStats {
- uint32_t VisitedInMainFile;
- uint32_t MissingInMainFile;
- uint32_t Visited;
- uint32_t Missing;
- uint32_t Mismatched;
-
-public:
- InstrProfStats()
- : VisitedInMainFile(0), MissingInMainFile(0), Visited(0), Missing(0),
- Mismatched(0) {}
- /// Record that we've visited a function and whether or not that function was
- /// in the main source file.
- void addVisited(bool MainFile) {
- if (MainFile)
- ++VisitedInMainFile;
- ++Visited;
- }
- /// Record that a function we've visited has no profile data.
- void addMissing(bool MainFile) {
- if (MainFile)
- ++MissingInMainFile;
- ++Missing;
- }
- /// Record that a function we've visited has mismatched profile data.
- void addMismatched(bool MainFile) { ++Mismatched; }
- /// Whether or not the stats we've gathered indicate any potential problems.
- bool hasDiagnostics() { return Missing || Mismatched; }
- /// Report potential problems we've found to \c Diags.
- void reportDiagnostics(DiagnosticsEngine &Diags, StringRef MainFile);
-};
-
-/// A pair of helper functions for a __block variable.
-class BlockByrefHelpers : public llvm::FoldingSetNode {
- // MSVC requires this type to be complete in order to process this
- // header.
-public:
- llvm::Constant *CopyHelper;
- llvm::Constant *DisposeHelper;
-
- /// The alignment of the field. This is important because
- /// different offsets to the field within the byref struct need to
- /// have different helper functions.
- CharUnits Alignment;
-
- BlockByrefHelpers(CharUnits alignment) : Alignment(alignment) {}
- BlockByrefHelpers(const BlockByrefHelpers &) = default;
- virtual ~BlockByrefHelpers();
-
- void Profile(llvm::FoldingSetNodeID &id) const {
- id.AddInteger(Alignment.getQuantity());
- profileImpl(id);
- }
- virtual void profileImpl(llvm::FoldingSetNodeID &id) const = 0;
-
- virtual bool needsCopy() const { return true; }
- virtual void emitCopy(CodeGenFunction &CGF, Address dest, Address src) = 0;
-
- virtual bool needsDispose() const { return true; }
- virtual void emitDispose(CodeGenFunction &CGF, Address field) = 0;
-};
-
-/// This class organizes the cross-function state that is used while generating
-/// LLVM code.
-class CodeGenModule : public CodeGenTypeCache {
- CodeGenModule(const CodeGenModule &) = delete;
- void operator=(const CodeGenModule &) = delete;
-
-public:
- struct Structor {
- Structor() : Priority(0), Initializer(nullptr), AssociatedData(nullptr) {}
- Structor(int Priority, llvm::Constant *Initializer,
- llvm::Constant *AssociatedData)
- : Priority(Priority), Initializer(Initializer),
- AssociatedData(AssociatedData) {}
- int Priority;
- llvm::Constant *Initializer;
- llvm::Constant *AssociatedData;
- };
-
- typedef std::vector<Structor> CtorList;
-
-private:
- ASTContext &Context;
- const LangOptions &LangOpts;
- const HeaderSearchOptions &HeaderSearchOpts; // Only used for debug info.
- const PreprocessorOptions &PreprocessorOpts; // Only used for debug info.
- const CodeGenOptions &CodeGenOpts;
- llvm::Module &TheModule;
- DiagnosticsEngine &Diags;
- const TargetInfo &Target;
- std::unique_ptr<CGCXXABI> ABI;
- llvm::LLVMContext &VMContext;
-
- CodeGenTBAA *TBAA;
-
- mutable const TargetCodeGenInfo *TheTargetCodeGenInfo;
-
- // This should not be moved earlier, since its initialization depends on some
- // of the previous reference members being already initialized and also checks
- // if TheTargetCodeGenInfo is NULL
- CodeGenTypes Types;
-
- /// Holds information about C++ vtables.
- CodeGenVTables VTables;
-
- CGObjCRuntime* ObjCRuntime;
- CGOpenCLRuntime* OpenCLRuntime;
- CGOpenMPRuntime* OpenMPRuntime;
- CGCUDARuntime* CUDARuntime;
- CGDebugInfo* DebugInfo;
- ObjCEntrypoints *ObjCData;
- llvm::MDNode *NoObjCARCExceptionsMetadata;
- std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader;
- InstrProfStats PGOStats;
-
- // A set of references that have only been seen via a weakref so far. This is
- // used to remove the weak of the reference if we ever see a direct reference
- // or a definition.
- llvm::SmallPtrSet<llvm::GlobalValue*, 10> WeakRefReferences;
-
- /// This contains all the decls which have definitions but/ which are deferred
- /// for emission and therefore should only be output if they are actually
- /// used. If a decl is in this, then it is known to have not been referenced
- /// yet.
- std::map<StringRef, GlobalDecl> DeferredDecls;
-
- /// This is a list of deferred decls which we have seen that *are* actually
- /// referenced. These get code generated when the module is done.
- struct DeferredGlobal {
- DeferredGlobal(llvm::GlobalValue *GV, GlobalDecl GD) : GV(GV), GD(GD) {}
- llvm::TrackingVH<llvm::GlobalValue> GV;
- GlobalDecl GD;
- };
- std::vector<DeferredGlobal> DeferredDeclsToEmit;
- void addDeferredDeclToEmit(llvm::GlobalValue *GV, GlobalDecl GD) {
- DeferredDeclsToEmit.emplace_back(GV, GD);
- }
-
- /// List of alias we have emitted. Used to make sure that what they point to
- /// is defined once we get to the end of the of the translation unit.
- std::vector<GlobalDecl> Aliases;
-
- typedef llvm::StringMap<llvm::TrackingVH<llvm::Constant> > ReplacementsTy;
- ReplacementsTy Replacements;
-
- /// List of global values to be replaced with something else. Used when we
- /// want to replace a GlobalValue but can't identify it by its mangled name
- /// anymore (because the name is already taken).
- llvm::SmallVector<std::pair<llvm::GlobalValue *, llvm::Constant *>, 8>
- GlobalValReplacements;
-
- /// Set of global decls for which we already diagnosed mangled name conflict.
- /// Required to not issue a warning (on a mangling conflict) multiple times
- /// for the same decl.
- llvm::DenseSet<GlobalDecl> DiagnosedConflictingDefinitions;
-
- /// A queue of (optional) vtables to consider emitting.
- std::vector<const CXXRecordDecl*> DeferredVTables;
-
- /// List of global values which are required to be present in the object file;
- /// bitcast to i8*. This is used for forcing visibility of symbols which may
- /// otherwise be optimized out.
- std::vector<llvm::WeakVH> LLVMUsed;
- std::vector<llvm::WeakVH> LLVMCompilerUsed;
-
- /// Store the list of global constructors and their respective priorities to
- /// be emitted when the translation unit is complete.
- CtorList GlobalCtors;
-
- /// Store the list of global destructors and their respective priorities to be
- /// emitted when the translation unit is complete.
- CtorList GlobalDtors;
-
- /// An ordered map of canonical GlobalDecls to their mangled names.
- llvm::MapVector<GlobalDecl, StringRef> MangledDeclNames;
- llvm::StringMap<GlobalDecl, llvm::BumpPtrAllocator> Manglings;
-
- /// Global annotations.
- std::vector<llvm::Constant*> Annotations;
-
- /// Map used to get unique annotation strings.
- llvm::StringMap<llvm::Constant*> AnnotationStrings;
-
- llvm::StringMap<llvm::GlobalVariable *> CFConstantStringMap;
-
- llvm::DenseMap<llvm::Constant *, llvm::GlobalVariable *> ConstantStringMap;
- llvm::DenseMap<const Decl*, llvm::Constant *> StaticLocalDeclMap;
- llvm::DenseMap<const Decl*, llvm::GlobalVariable*> StaticLocalDeclGuardMap;
- llvm::DenseMap<const Expr*, llvm::Constant *> MaterializedGlobalTemporaryMap;
-
- llvm::DenseMap<QualType, llvm::Constant *> AtomicSetterHelperFnMap;
- llvm::DenseMap<QualType, llvm::Constant *> AtomicGetterHelperFnMap;
-
- /// Map used to get unique type descriptor constants for sanitizers.
- llvm::DenseMap<QualType, llvm::Constant *> TypeDescriptorMap;
-
- /// Map used to track internal linkage functions declared within
- /// extern "C" regions.
- typedef llvm::MapVector<IdentifierInfo *,
- llvm::GlobalValue *> StaticExternCMap;
- StaticExternCMap StaticExternCValues;
-
- /// \brief thread_local variables defined or used in this TU.
- std::vector<const VarDecl *> CXXThreadLocals;
-
- /// \brief thread_local variables with initializers that need to run
- /// before any thread_local variable in this TU is odr-used.
- std::vector<llvm::Function *> CXXThreadLocalInits;
- std::vector<const VarDecl *> CXXThreadLocalInitVars;
-
- /// Global variables with initializers that need to run before main.
- std::vector<llvm::Function *> CXXGlobalInits;
-
- /// When a C++ decl with an initializer is deferred, null is
- /// appended to CXXGlobalInits, and the index of that null is placed
- /// here so that the initializer will be performed in the correct
- /// order. Once the decl is emitted, the index is replaced with ~0U to ensure
- /// that we don't re-emit the initializer.
- llvm::DenseMap<const Decl*, unsigned> DelayedCXXInitPosition;
-
- typedef std::pair<OrderGlobalInits, llvm::Function*> GlobalInitData;
-
- struct GlobalInitPriorityCmp {
- bool operator()(const GlobalInitData &LHS,
- const GlobalInitData &RHS) const {
- return LHS.first.priority < RHS.first.priority;
- }
- };
-
- /// Global variables with initializers whose order of initialization is set by
- /// init_priority attribute.
- SmallVector<GlobalInitData, 8> PrioritizedCXXGlobalInits;
-
- /// Global destructor functions and arguments that need to run on termination.
- std::vector<std::pair<llvm::WeakVH,llvm::Constant*> > CXXGlobalDtors;
-
- /// \brief The complete set of modules that has been imported.
- llvm::SetVector<clang::Module *> ImportedModules;
-
- /// \brief A vector of metadata strings.
- SmallVector<llvm::Metadata *, 16> LinkerOptionsMetadata;
-
- /// @name Cache for Objective-C runtime types
- /// @{
-
- /// Cached reference to the class for constant strings. This value has type
- /// int * but is actually an Obj-C class pointer.
- llvm::WeakVH CFConstantStringClassRef;
-
- /// Cached reference to the class for constant strings. This value has type
- /// int * but is actually an Obj-C class pointer.
- llvm::WeakVH ConstantStringClassRef;
-
- /// \brief The LLVM type corresponding to NSConstantString.
- llvm::StructType *NSConstantStringType;
-
- /// \brief The type used to describe the state of a fast enumeration in
- /// Objective-C's for..in loop.
- QualType ObjCFastEnumerationStateType;
-
- /// @}
-
- /// Lazily create the Objective-C runtime
- void createObjCRuntime();
-
- void createOpenCLRuntime();
- void createOpenMPRuntime();
- void createCUDARuntime();
-
- bool isTriviallyRecursive(const FunctionDecl *F);
- bool shouldEmitFunction(GlobalDecl GD);
-
- /// @name Cache for Blocks Runtime Globals
- /// @{
-
- llvm::Constant *NSConcreteGlobalBlock;
- llvm::Constant *NSConcreteStackBlock;
-
- llvm::Constant *BlockObjectAssign;
- llvm::Constant *BlockObjectDispose;
-
- llvm::Type *BlockDescriptorType;
- llvm::Type *GenericBlockLiteralType;
-
- struct {
- int GlobalUniqueCount;
- } Block;
-
- /// void @llvm.lifetime.start(i64 %size, i8* nocapture <ptr>)
- llvm::Constant *LifetimeStartFn;
-
- /// void @llvm.lifetime.end(i64 %size, i8* nocapture <ptr>)
- llvm::Constant *LifetimeEndFn;
-
- GlobalDecl initializedGlobalDecl;
-
- std::unique_ptr<SanitizerMetadata> SanitizerMD;
-
- /// @}
-
- llvm::DenseMap<const Decl *, bool> DeferredEmptyCoverageMappingDecls;
-
- std::unique_ptr<CoverageMappingModuleGen> CoverageMapping;
-
- /// Mapping from canonical types to their metadata identifiers. We need to
- /// maintain this mapping because identifiers may be formed from distinct
- /// MDNodes.
- llvm::DenseMap<QualType, llvm::Metadata *> MetadataIdMap;
-
-public:
- CodeGenModule(ASTContext &C, const HeaderSearchOptions &headersearchopts,
- const PreprocessorOptions &ppopts,
- const CodeGenOptions &CodeGenOpts, llvm::Module &M,
- DiagnosticsEngine &Diags,
- CoverageSourceInfo *CoverageInfo = nullptr);
-
- ~CodeGenModule();
-
- void clear();
-
- /// Finalize LLVM code generation.
- void Release();
-
- /// Return a reference to the configured Objective-C runtime.
- CGObjCRuntime &getObjCRuntime() {
- if (!ObjCRuntime) createObjCRuntime();
- return *ObjCRuntime;
- }
-
- /// Return true iff an Objective-C runtime has been configured.
- bool hasObjCRuntime() { return !!ObjCRuntime; }
-
- /// Return a reference to the configured OpenCL runtime.
- CGOpenCLRuntime &getOpenCLRuntime() {
- assert(OpenCLRuntime != nullptr);
- return *OpenCLRuntime;
- }
-
- /// Return a reference to the configured OpenMP runtime.
- CGOpenMPRuntime &getOpenMPRuntime() {
- assert(OpenMPRuntime != nullptr);
- return *OpenMPRuntime;
- }
-
- /// Return a reference to the configured CUDA runtime.
- CGCUDARuntime &getCUDARuntime() {
- assert(CUDARuntime != nullptr);
- return *CUDARuntime;
- }
-
- ObjCEntrypoints &getObjCEntrypoints() const {
- assert(ObjCData != nullptr);
- return *ObjCData;
- }
-
- InstrProfStats &getPGOStats() { return PGOStats; }
- llvm::IndexedInstrProfReader *getPGOReader() const { return PGOReader.get(); }
-
- CoverageMappingModuleGen *getCoverageMapping() const {
- return CoverageMapping.get();
- }
-
- llvm::Constant *getStaticLocalDeclAddress(const VarDecl *D) {
- return StaticLocalDeclMap[D];
- }
- void setStaticLocalDeclAddress(const VarDecl *D,
- llvm::Constant *C) {
- StaticLocalDeclMap[D] = C;
- }
-
- llvm::Constant *
- getOrCreateStaticVarDecl(const VarDecl &D,
- llvm::GlobalValue::LinkageTypes Linkage);
-
- llvm::GlobalVariable *getStaticLocalDeclGuardAddress(const VarDecl *D) {
- return StaticLocalDeclGuardMap[D];
- }
- void setStaticLocalDeclGuardAddress(const VarDecl *D,
- llvm::GlobalVariable *C) {
- StaticLocalDeclGuardMap[D] = C;
- }
-
- bool lookupRepresentativeDecl(StringRef MangledName,
- GlobalDecl &Result) const;
-
- llvm::Constant *getAtomicSetterHelperFnMap(QualType Ty) {
- return AtomicSetterHelperFnMap[Ty];
- }
- void setAtomicSetterHelperFnMap(QualType Ty,
- llvm::Constant *Fn) {
- AtomicSetterHelperFnMap[Ty] = Fn;
- }
-
- llvm::Constant *getAtomicGetterHelperFnMap(QualType Ty) {
- return AtomicGetterHelperFnMap[Ty];
- }
- void setAtomicGetterHelperFnMap(QualType Ty,
- llvm::Constant *Fn) {
- AtomicGetterHelperFnMap[Ty] = Fn;
- }
-
- llvm::Constant *getTypeDescriptorFromMap(QualType Ty) {
- return TypeDescriptorMap[Ty];
- }
- void setTypeDescriptorInMap(QualType Ty, llvm::Constant *C) {
- TypeDescriptorMap[Ty] = C;
- }
-
- CGDebugInfo *getModuleDebugInfo() { return DebugInfo; }
-
- llvm::MDNode *getNoObjCARCExceptionsMetadata() {
- if (!NoObjCARCExceptionsMetadata)
- NoObjCARCExceptionsMetadata = llvm::MDNode::get(getLLVMContext(), None);
- return NoObjCARCExceptionsMetadata;
- }
-
- ASTContext &getContext() const { return Context; }
- const LangOptions &getLangOpts() const { return LangOpts; }
- const HeaderSearchOptions &getHeaderSearchOpts()
- const { return HeaderSearchOpts; }
- const PreprocessorOptions &getPreprocessorOpts()
- const { return PreprocessorOpts; }
- const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; }
- llvm::Module &getModule() const { return TheModule; }
- DiagnosticsEngine &getDiags() const { return Diags; }
- const llvm::DataLayout &getDataLayout() const {
- return TheModule.getDataLayout();
- }
- const TargetInfo &getTarget() const { return Target; }
- const llvm::Triple &getTriple() const;
- bool supportsCOMDAT() const;
- void maybeSetTrivialComdat(const Decl &D, llvm::GlobalObject &GO);
-
- CGCXXABI &getCXXABI() const { return *ABI; }
- llvm::LLVMContext &getLLVMContext() { return VMContext; }
-
- bool shouldUseTBAA() const { return TBAA != nullptr; }
-
- const TargetCodeGenInfo &getTargetCodeGenInfo();
-
- CodeGenTypes &getTypes() { return Types; }
-
- CodeGenVTables &getVTables() { return VTables; }
-
- ItaniumVTableContext &getItaniumVTableContext() {
- return VTables.getItaniumVTableContext();
- }
-
- MicrosoftVTableContext &getMicrosoftVTableContext() {
- return VTables.getMicrosoftVTableContext();
- }
-
- CtorList &getGlobalCtors() { return GlobalCtors; }
- CtorList &getGlobalDtors() { return GlobalDtors; }
-
- llvm::MDNode *getTBAAInfo(QualType QTy);
- llvm::MDNode *getTBAAInfoForVTablePtr();
- llvm::MDNode *getTBAAStructInfo(QualType QTy);
- /// Return the path-aware tag for given base type, access node and offset.
- llvm::MDNode *getTBAAStructTagInfo(QualType BaseTy, llvm::MDNode *AccessN,
- uint64_t O);
-
- bool isTypeConstant(QualType QTy, bool ExcludeCtorDtor);
-
- bool isPaddedAtomicType(QualType type);
- bool isPaddedAtomicType(const AtomicType *type);
-
- /// Decorate the instruction with a TBAA tag. For scalar TBAA, the tag
- /// is the same as the type. For struct-path aware TBAA, the tag
- /// is different from the type: base type, access type and offset.
- /// When ConvertTypeToTag is true, we create a tag based on the scalar type.
- void DecorateInstructionWithTBAA(llvm::Instruction *Inst,
- llvm::MDNode *TBAAInfo,
- bool ConvertTypeToTag = true);
-
- /// Adds !invariant.barrier !tag to instruction
- void DecorateInstructionWithInvariantGroup(llvm::Instruction *I,
- const CXXRecordDecl *RD);
-
- /// Emit the given number of characters as a value of type size_t.
- llvm::ConstantInt *getSize(CharUnits numChars);
-
- /// Set the visibility for the given LLVM GlobalValue.
- void setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D) const;
-
- /// Set the TLS mode for the given LLVM GlobalValue for the thread-local
- /// variable declaration D.
- void setTLSMode(llvm::GlobalValue *GV, const VarDecl &D) const;
-
- static llvm::GlobalValue::VisibilityTypes GetLLVMVisibility(Visibility V) {
- switch (V) {
- case DefaultVisibility: return llvm::GlobalValue::DefaultVisibility;
- case HiddenVisibility: return llvm::GlobalValue::HiddenVisibility;
- case ProtectedVisibility: return llvm::GlobalValue::ProtectedVisibility;
- }
- llvm_unreachable("unknown visibility!");
- }
-
- llvm::Constant *GetAddrOfGlobal(GlobalDecl GD, bool IsForDefinition = false);
-
- /// Will return a global variable of the given type. If a variable with a
- /// different type already exists then a new variable with the right type
- /// will be created and all uses of the old variable will be replaced with a
- /// bitcast to the new variable.
- llvm::GlobalVariable *
- CreateOrReplaceCXXRuntimeVariable(StringRef Name, llvm::Type *Ty,
- llvm::GlobalValue::LinkageTypes Linkage);
-
- llvm::Function *
- CreateGlobalInitOrDestructFunction(llvm::FunctionType *ty, const Twine &name,
- const CGFunctionInfo &FI,
- SourceLocation Loc = SourceLocation(),
- bool TLS = false);
-
- /// Return the address space of the underlying global variable for D, as
- /// determined by its declaration. Normally this is the same as the address
- /// space of D's type, but in CUDA, address spaces are associated with
- /// declarations, not types.
- unsigned GetGlobalVarAddressSpace(const VarDecl *D, unsigned AddrSpace);
-
- /// Return the llvm::Constant for the address of the given global variable.
- /// If Ty is non-null and if the global doesn't exist, then it will be greated
- /// with the specified type instead of whatever the normal requested type
- /// would be.
- llvm::Constant *GetAddrOfGlobalVar(const VarDecl *D,
- llvm::Type *Ty = nullptr);
-
- /// Return the address of the given function. If Ty is non-null, then this
- /// function will use the specified type if it has to create it.
- llvm::Constant *GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty = nullptr,
- bool ForVTable = false,
- bool DontDefer = false,
- bool IsForDefinition = false);
-
- /// Get the address of the RTTI descriptor for the given type.
- llvm::Constant *GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH = false);
-
- /// Get the address of a uuid descriptor .
- ConstantAddress GetAddrOfUuidDescriptor(const CXXUuidofExpr* E);
-
- /// Get the address of the thunk for the given global decl.
- llvm::Constant *GetAddrOfThunk(GlobalDecl GD, const ThunkInfo &Thunk);
-
- /// Get a reference to the target of VD.
- ConstantAddress GetWeakRefReference(const ValueDecl *VD);
-
- /// Returns the assumed alignment of an opaque pointer to the given class.
- CharUnits getClassPointerAlignment(const CXXRecordDecl *CD);
-
- /// Returns the assumed alignment of a virtual base of a class.
- CharUnits getVBaseAlignment(CharUnits DerivedAlign,
- const CXXRecordDecl *Derived,
- const CXXRecordDecl *VBase);
-
- /// Given a class pointer with an actual known alignment, and the
- /// expected alignment of an object at a dynamic offset w.r.t that
- /// pointer, return the alignment to assume at the offset.
- CharUnits getDynamicOffsetAlignment(CharUnits ActualAlign,
- const CXXRecordDecl *Class,
- CharUnits ExpectedTargetAlign);
-
- CharUnits
- computeNonVirtualBaseClassOffset(const CXXRecordDecl *DerivedClass,
- CastExpr::path_const_iterator Start,
- CastExpr::path_const_iterator End);
-
- /// Returns the offset from a derived class to a class. Returns null if the
- /// offset is 0.
- llvm::Constant *
- GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl,
- CastExpr::path_const_iterator PathBegin,
- CastExpr::path_const_iterator PathEnd);
-
- llvm::FoldingSet<BlockByrefHelpers> ByrefHelpersCache;
-
- /// Fetches the global unique block count.
- int getUniqueBlockCount() { return ++Block.GlobalUniqueCount; }
-
- /// Fetches the type of a generic block descriptor.
- llvm::Type *getBlockDescriptorType();
-
- /// The type of a generic block literal.
- llvm::Type *getGenericBlockLiteralType();
-
- /// Gets the address of a block which requires no captures.
- llvm::Constant *GetAddrOfGlobalBlock(const BlockExpr *BE, const char *);
-
- /// Return a pointer to a constant CFString object for the given string.
- ConstantAddress GetAddrOfConstantCFString(const StringLiteral *Literal);
-
- /// Return a pointer to a constant NSString object for the given string. Or a
- /// user defined String object as defined via
- /// -fconstant-string-class=class_name option.
- ConstantAddress GetAddrOfConstantString(const StringLiteral *Literal);
-
- /// Return a constant array for the given string.
- llvm::Constant *GetConstantArrayFromStringLiteral(const StringLiteral *E);
-
- /// Return a pointer to a constant array for the given string literal.
- ConstantAddress
- GetAddrOfConstantStringFromLiteral(const StringLiteral *S,
- StringRef Name = ".str");
-
- /// Return a pointer to a constant array for the given ObjCEncodeExpr node.
- ConstantAddress
- GetAddrOfConstantStringFromObjCEncode(const ObjCEncodeExpr *);
-
- /// Returns a pointer to a character array containing the literal and a
- /// terminating '\0' character. The result has pointer to array type.
- ///
- /// \param GlobalName If provided, the name to use for the global (if one is
- /// created).
- ConstantAddress
- GetAddrOfConstantCString(const std::string &Str,
- const char *GlobalName = nullptr);
-
- /// Returns a pointer to a constant global variable for the given file-scope
- /// compound literal expression.
- ConstantAddress GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr*E);
-
- /// \brief Returns a pointer to a global variable representing a temporary
- /// with static or thread storage duration.
- ConstantAddress GetAddrOfGlobalTemporary(const MaterializeTemporaryExpr *E,
- const Expr *Inner);
-
- /// \brief Retrieve the record type that describes the state of an
- /// Objective-C fast enumeration loop (for..in).
- QualType getObjCFastEnumerationStateType();
-
- // Produce code for this constructor/destructor. This method doesn't try
- // to apply any ABI rules about which other constructors/destructors
- // are needed or if they are alias to each other.
- llvm::Function *codegenCXXStructor(const CXXMethodDecl *MD,
- StructorType Type);
-
- /// Return the address of the constructor/destructor of the given type.
- llvm::Constant *
- getAddrOfCXXStructor(const CXXMethodDecl *MD, StructorType Type,
- const CGFunctionInfo *FnInfo = nullptr,
- llvm::FunctionType *FnType = nullptr,
- bool DontDefer = false, bool IsForDefinition = false);
-
- /// Given a builtin id for a function like "__builtin_fabsf", return a
- /// Function* for "fabsf".
- llvm::Value *getBuiltinLibFunction(const FunctionDecl *FD,
- unsigned BuiltinID);
-
- llvm::Function *getIntrinsic(unsigned IID, ArrayRef<llvm::Type*> Tys = None);
-
- /// Emit code for a single top level declaration.
- void EmitTopLevelDecl(Decl *D);
-
- /// \brief Stored a deferred empty coverage mapping for an unused
- /// and thus uninstrumented top level declaration.
- void AddDeferredUnusedCoverageMapping(Decl *D);
-
- /// \brief Remove the deferred empty coverage mapping as this
- /// declaration is actually instrumented.
- void ClearUnusedCoverageMapping(const Decl *D);
-
- /// \brief Emit all the deferred coverage mappings
- /// for the uninstrumented functions.
- void EmitDeferredUnusedCoverageMappings();
-
- /// Tell the consumer that this variable has been instantiated.
- void HandleCXXStaticMemberVarInstantiation(VarDecl *VD);
-
- /// \brief If the declaration has internal linkage but is inside an
- /// extern "C" linkage specification, prepare to emit an alias for it
- /// to the expected name.
- template<typename SomeDecl>
- void MaybeHandleStaticInExternC(const SomeDecl *D, llvm::GlobalValue *GV);
-
- /// Add a global to a list to be added to the llvm.used metadata.
- void addUsedGlobal(llvm::GlobalValue *GV);
-
- /// Add a global to a list to be added to the llvm.compiler.used metadata.
- void addCompilerUsedGlobal(llvm::GlobalValue *GV);
-
- /// Add a destructor and object to add to the C++ global destructor function.
- void AddCXXDtorEntry(llvm::Constant *DtorFn, llvm::Constant *Object) {
- CXXGlobalDtors.emplace_back(DtorFn, Object);
- }
-
- /// Create a new runtime function with the specified type and name.
- llvm::Constant *CreateRuntimeFunction(llvm::FunctionType *Ty,
- StringRef Name,
- llvm::AttributeSet ExtraAttrs =
- llvm::AttributeSet());
- /// Create a new compiler builtin function with the specified type and name.
- llvm::Constant *CreateBuiltinFunction(llvm::FunctionType *Ty,
- StringRef Name,
- llvm::AttributeSet ExtraAttrs =
- llvm::AttributeSet());
- /// Create a new runtime global variable with the specified type and name.
- llvm::Constant *CreateRuntimeVariable(llvm::Type *Ty,
- StringRef Name);
-
- ///@name Custom Blocks Runtime Interfaces
- ///@{
-
- llvm::Constant *getNSConcreteGlobalBlock();
- llvm::Constant *getNSConcreteStackBlock();
- llvm::Constant *getBlockObjectAssign();
- llvm::Constant *getBlockObjectDispose();
-
- ///@}
-
- llvm::Constant *getLLVMLifetimeStartFn();
- llvm::Constant *getLLVMLifetimeEndFn();
-
- // Make sure that this type is translated.
- void UpdateCompletedType(const TagDecl *TD);
-
- llvm::Constant *getMemberPointerConstant(const UnaryOperator *e);
-
- /// Try to emit the initializer for the given declaration as a constant;
- /// returns 0 if the expression cannot be emitted as a constant.
- llvm::Constant *EmitConstantInit(const VarDecl &D,
- CodeGenFunction *CGF = nullptr);
-
- /// Try to emit the given expression as a constant; returns 0 if the
- /// expression cannot be emitted as a constant.
- llvm::Constant *EmitConstantExpr(const Expr *E, QualType DestType,
- CodeGenFunction *CGF = nullptr);
-
- /// Emit the given constant value as a constant, in the type's scalar
- /// representation.
- llvm::Constant *EmitConstantValue(const APValue &Value, QualType DestType,
- CodeGenFunction *CGF = nullptr);
-
- /// Emit the given constant value as a constant, in the type's memory
- /// representation.
- llvm::Constant *EmitConstantValueForMemory(const APValue &Value,
- QualType DestType,
- CodeGenFunction *CGF = nullptr);
-
- /// \brief Emit type info if type of an expression is a variably modified
- /// type. Also emit proper debug info for cast types.
- void EmitExplicitCastExprType(const ExplicitCastExpr *E,
- CodeGenFunction *CGF = nullptr);
-
- /// Return the result of value-initializing the given type, i.e. a null
- /// expression of the given type. This is usually, but not always, an LLVM
- /// null constant.
- llvm::Constant *EmitNullConstant(QualType T);
-
- /// Return a null constant appropriate for zero-initializing a base class with
- /// the given type. This is usually, but not always, an LLVM null constant.
- llvm::Constant *EmitNullConstantForBase(const CXXRecordDecl *Record);
-
- /// Emit a general error that something can't be done.
- void Error(SourceLocation loc, StringRef error);
-
- /// Print out an error that codegen doesn't support the specified stmt yet.
- void ErrorUnsupported(const Stmt *S, const char *Type);
-
- /// Print out an error that codegen doesn't support the specified decl yet.
- void ErrorUnsupported(const Decl *D, const char *Type);
-
- /// Set the attributes on the LLVM function for the given decl and function
- /// info. This applies attributes necessary for handling the ABI as well as
- /// user specified attributes like section.
- void SetInternalFunctionAttributes(const Decl *D, llvm::Function *F,
- const CGFunctionInfo &FI);
-
- /// Set the LLVM function attributes (sext, zext, etc).
- void SetLLVMFunctionAttributes(const Decl *D,
- const CGFunctionInfo &Info,
- llvm::Function *F);
-
- /// Set the LLVM function attributes which only apply to a function
- /// definition.
- void SetLLVMFunctionAttributesForDefinition(const Decl *D, llvm::Function *F);
-
- /// Return true iff the given type uses 'sret' when used as a return type.
- bool ReturnTypeUsesSRet(const CGFunctionInfo &FI);
-
- /// Return true iff the given type uses an argument slot when 'sret' is used
- /// as a return type.
- bool ReturnSlotInterferesWithArgs(const CGFunctionInfo &FI);
-
- /// Return true iff the given type uses 'fpret' when used as a return type.
- bool ReturnTypeUsesFPRet(QualType ResultType);
-
- /// Return true iff the given type uses 'fp2ret' when used as a return type.
- bool ReturnTypeUsesFP2Ret(QualType ResultType);
-
- /// Get the LLVM attributes and calling convention to use for a particular
- /// function type.
- ///
- /// \param Name - The function name.
- /// \param Info - The function type information.
- /// \param CalleeInfo - The callee information these attributes are being
- /// constructed for. If valid, the attributes applied to this decl may
- /// contribute to the function attributes and calling convention.
- /// \param PAL [out] - On return, the attribute list to use.
- /// \param CallingConv [out] - On return, the LLVM calling convention to use.
- void ConstructAttributeList(StringRef Name, const CGFunctionInfo &Info,
- CGCalleeInfo CalleeInfo, AttributeListType &PAL,
- unsigned &CallingConv, bool AttrOnCallSite);
-
- // Fills in the supplied string map with the set of target features for the
- // passed in function.
- void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
- const FunctionDecl *FD);
-
- StringRef getMangledName(GlobalDecl GD);
- StringRef getBlockMangledName(GlobalDecl GD, const BlockDecl *BD);
-
- void EmitTentativeDefinition(const VarDecl *D);
-
- void EmitVTable(CXXRecordDecl *Class);
-
- /// \brief Appends Opts to the "Linker Options" metadata value.
- void AppendLinkerOptions(StringRef Opts);
-
- /// \brief Appends a detect mismatch command to the linker options.
- void AddDetectMismatch(StringRef Name, StringRef Value);
-
- /// \brief Appends a dependent lib to the "Linker Options" metadata value.
- void AddDependentLib(StringRef Lib);
-
- llvm::GlobalVariable::LinkageTypes getFunctionLinkage(GlobalDecl GD);
-
- void setFunctionLinkage(GlobalDecl GD, llvm::Function *F) {
- F->setLinkage(getFunctionLinkage(GD));
- }
-
- /// Set the DLL storage class on F.
- void setFunctionDLLStorageClass(GlobalDecl GD, llvm::Function *F);
-
- /// Return the appropriate linkage for the vtable, VTT, and type information
- /// of the given class.
- llvm::GlobalVariable::LinkageTypes getVTableLinkage(const CXXRecordDecl *RD);
-
- /// Return the store size, in character units, of the given LLVM type.
- CharUnits GetTargetTypeStoreSize(llvm::Type *Ty) const;
-
- /// Returns LLVM linkage for a declarator.
- llvm::GlobalValue::LinkageTypes
- getLLVMLinkageForDeclarator(const DeclaratorDecl *D, GVALinkage Linkage,
- bool IsConstantVariable);
-
- /// Returns LLVM linkage for a declarator.
- llvm::GlobalValue::LinkageTypes
- getLLVMLinkageVarDefinition(const VarDecl *VD, bool IsConstant);
-
- /// Emit all the global annotations.
- void EmitGlobalAnnotations();
-
- /// Emit an annotation string.
- llvm::Constant *EmitAnnotationString(StringRef Str);
-
- /// Emit the annotation's translation unit.
- llvm::Constant *EmitAnnotationUnit(SourceLocation Loc);
-
- /// Emit the annotation line number.
- llvm::Constant *EmitAnnotationLineNo(SourceLocation L);
-
- /// Generate the llvm::ConstantStruct which contains the annotation
- /// information for a given GlobalValue. The annotation struct is
- /// {i8 *, i8 *, i8 *, i32}. The first field is a constant expression, the
- /// GlobalValue being annotated. The second field is the constant string
- /// created from the AnnotateAttr's annotation. The third field is a constant
- /// string containing the name of the translation unit. The fourth field is
- /// the line number in the file of the annotated value declaration.
- llvm::Constant *EmitAnnotateAttr(llvm::GlobalValue *GV,
- const AnnotateAttr *AA,
- SourceLocation L);
-
- /// Add global annotations that are set on D, for the global GV. Those
- /// annotations are emitted during finalization of the LLVM code.
- void AddGlobalAnnotations(const ValueDecl *D, llvm::GlobalValue *GV);
-
- bool isInSanitizerBlacklist(llvm::Function *Fn, SourceLocation Loc) const;
-
- bool isInSanitizerBlacklist(llvm::GlobalVariable *GV, SourceLocation Loc,
- QualType Ty,
- StringRef Category = StringRef()) const;
-
- SanitizerMetadata *getSanitizerMetadata() {
- return SanitizerMD.get();
- }
-
- void addDeferredVTable(const CXXRecordDecl *RD) {
- DeferredVTables.push_back(RD);
- }
-
- /// Emit code for a singal global function or var decl. Forward declarations
- /// are emitted lazily.
- void EmitGlobal(GlobalDecl D);
-
- bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target,
- bool InEveryTU);
- bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D);
-
- /// Set attributes for a global definition.
- void setFunctionDefinitionAttributes(const FunctionDecl *D,
- llvm::Function *F);
-
- llvm::GlobalValue *GetGlobalValue(StringRef Ref);
-
- /// Set attributes which are common to any form of a global definition (alias,
- /// Objective-C method, function, global variable).
- ///
- /// NOTE: This should only be called for definitions.
- void SetCommonAttributes(const Decl *D, llvm::GlobalValue *GV);
-
- /// Set attributes which must be preserved by an alias. This includes common
- /// attributes (i.e. it includes a call to SetCommonAttributes).
- ///
- /// NOTE: This should only be called for definitions.
- void setAliasAttributes(const Decl *D, llvm::GlobalValue *GV);
-
- void addReplacement(StringRef Name, llvm::Constant *C);
-
- void addGlobalValReplacement(llvm::GlobalValue *GV, llvm::Constant *C);
-
- /// \brief Emit a code for threadprivate directive.
- /// \param D Threadprivate declaration.
- void EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D);
-
- /// Returns whether the given record is blacklisted from control flow
- /// integrity checks.
- bool IsCFIBlacklistedRecord(const CXXRecordDecl *RD);
-
- /// Emit bit set entries for the given vtable using the given layout if
- /// vptr CFI is enabled.
- void EmitVTableBitSetEntries(llvm::GlobalVariable *VTable,
- const VTableLayout &VTLayout);
-
- /// Generate a cross-DSO type identifier for type.
- llvm::ConstantInt *CreateCfiIdForTypeMetadata(llvm::Metadata *MD);
-
- /// Create a metadata identifier for the given type. This may either be an
- /// MDString (for external identifiers) or a distinct unnamed MDNode (for
- /// internal identifiers).
- llvm::Metadata *CreateMetadataIdentifierForType(QualType T);
-
- /// Create a bitset entry for the given function and add it to BitsetsMD.
- void CreateFunctionBitSetEntry(const FunctionDecl *FD, llvm::Function *F);
-
- /// Create a bitset entry for the given vtable and add it to BitsetsMD.
- void CreateVTableBitSetEntry(llvm::NamedMDNode *BitsetsMD,
- llvm::GlobalVariable *VTable, CharUnits Offset,
- const CXXRecordDecl *RD);
-
- /// \breif Get the declaration of std::terminate for the platform.
- llvm::Constant *getTerminateFn();
-
-private:
- llvm::Constant *
- GetOrCreateLLVMFunction(StringRef MangledName, llvm::Type *Ty, GlobalDecl D,
- bool ForVTable, bool DontDefer = false,
- bool IsThunk = false,
- llvm::AttributeSet ExtraAttrs = llvm::AttributeSet(),
- bool IsForDefinition = false);
-
- llvm::Constant *GetOrCreateLLVMGlobal(StringRef MangledName,
- llvm::PointerType *PTy,
- const VarDecl *D);
-
- void setNonAliasAttributes(const Decl *D, llvm::GlobalObject *GO);
-
- /// Set function attributes for a function declaration.
- void SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
- bool IsIncompleteFunction, bool IsThunk);
-
- void EmitGlobalDefinition(GlobalDecl D, llvm::GlobalValue *GV = nullptr);
-
- void EmitGlobalFunctionDefinition(GlobalDecl GD, llvm::GlobalValue *GV);
- void EmitGlobalVarDefinition(const VarDecl *D);
- void EmitAliasDefinition(GlobalDecl GD);
- void EmitObjCPropertyImplementations(const ObjCImplementationDecl *D);
- void EmitObjCIvarInitializations(ObjCImplementationDecl *D);
-
- // C++ related functions.
-
- void EmitNamespace(const NamespaceDecl *D);
- void EmitLinkageSpec(const LinkageSpecDecl *D);
- void CompleteDIClassType(const CXXMethodDecl* D);
-
- /// \brief Emit the function that initializes C++ thread_local variables.
- void EmitCXXThreadLocalInitFunc();
-
- /// Emit the function that initializes C++ globals.
- void EmitCXXGlobalInitFunc();
-
- /// Emit the function that destroys C++ globals.
- void EmitCXXGlobalDtorFunc();
-
- /// Emit the function that initializes the specified global (if PerformInit is
- /// true) and registers its destructor.
- void EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
- llvm::GlobalVariable *Addr,
- bool PerformInit);
-
- void EmitPointerToInitFunc(const VarDecl *VD, llvm::GlobalVariable *Addr,
- llvm::Function *InitFunc, InitSegAttr *ISA);
-
- // FIXME: Hardcoding priority here is gross.
- void AddGlobalCtor(llvm::Function *Ctor, int Priority = 65535,
- llvm::Constant *AssociatedData = nullptr);
- void AddGlobalDtor(llvm::Function *Dtor, int Priority = 65535);
-
- /// Generates a global array of functions and priorities using the given list
- /// and name. This array will have appending linkage and is suitable for use
- /// as a LLVM constructor or destructor array.
- void EmitCtorList(const CtorList &Fns, const char *GlobalName);
-
- /// Emit any needed decls for which code generation was deferred.
- void EmitDeferred();
-
- /// Call replaceAllUsesWith on all pairs in Replacements.
- void applyReplacements();
-
- /// Call replaceAllUsesWith on all pairs in GlobalValReplacements.
- void applyGlobalValReplacements();
-
- void checkAliases();
-
- /// Emit any vtables which we deferred and still have a use for.
- void EmitDeferredVTables();
-
- /// Emit the llvm.used and llvm.compiler.used metadata.
- void emitLLVMUsed();
-
- /// \brief Emit the link options introduced by imported modules.
- void EmitModuleLinkOptions();
-
- /// \brief Emit aliases for internal-linkage declarations inside "C" language
- /// linkage specifications, giving them the "expected" name where possible.
- void EmitStaticExternCAliases();
-
- void EmitDeclMetadata();
-
- /// \brief Emit the Clang version as llvm.ident metadata.
- void EmitVersionIdentMetadata();
-
- /// Emits target specific Metadata for global declarations.
- void EmitTargetMetadata();
-
- /// Emit the llvm.gcov metadata used to tell LLVM where to emit the .gcno and
- /// .gcda files in a way that persists in .bc files.
- void EmitCoverageFile();
-
- /// Emits the initializer for a uuidof string.
- llvm::Constant *EmitUuidofInitializer(StringRef uuidstr);
-
- /// Determine whether the definition must be emitted; if this returns \c
- /// false, the definition can be emitted lazily if it's used.
- bool MustBeEmitted(const ValueDecl *D);
-
- /// Determine whether the definition can be emitted eagerly, or should be
- /// delayed until the end of the translation unit. This is relevant for
- /// definitions whose linkage can change, e.g. implicit function instantions
- /// which may later be explicitly instantiated.
- bool MayBeEmittedEagerly(const ValueDecl *D);
-
- /// Check whether we can use a "simpler", more core exceptions personality
- /// function.
- void SimplifyPersonality();
-};
-} // end namespace CodeGen
-} // end namespace clang
-
-#endif // LLVM_CLANG_LIB_CODEGEN_CODEGENMODULE_H
diff --git a/vendors/clang-codegen-private-3.8/CodeGenTypeCache.h b/vendors/clang-codegen-private-3.8/CodeGenTypeCache.h
deleted file mode 100644
index c32b66d..0000000
--- a/vendors/clang-codegen-private-3.8/CodeGenTypeCache.h
+++ /dev/null
@@ -1,108 +0,0 @@
-//===--- CodeGenTypeCache.h - Commonly used LLVM types and info -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This structure provides a set of common types useful during IR emission.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_CODEGEN_CODEGENTYPECACHE_H
-#define LLVM_CLANG_LIB_CODEGEN_CODEGENTYPECACHE_H
-
-#include "clang/AST/CharUnits.h"
-#include "llvm/IR/CallingConv.h"
-
-namespace llvm {
- class Type;
- class IntegerType;
- class PointerType;
-}
-
-namespace clang {
-namespace CodeGen {
-
-/// This structure provides a set of types that are commonly used
-/// during IR emission. It's initialized once in CodeGenModule's
-/// constructor and then copied around into new CodeGenFunctions.
-struct CodeGenTypeCache {
- /// void
- llvm::Type *VoidTy;
-
- /// i8, i16, i32, and i64
- llvm::IntegerType *Int8Ty, *Int16Ty, *Int32Ty, *Int64Ty;
- /// float, double
- llvm::Type *FloatTy, *DoubleTy;
-
- /// int
- llvm::IntegerType *IntTy;
-
- /// intptr_t, size_t, and ptrdiff_t, which we assume are the same size.
- union {
- llvm::IntegerType *IntPtrTy;
- llvm::IntegerType *SizeTy;
- llvm::IntegerType *PtrDiffTy;
- };
-
- /// void* in address space 0
- union {
- llvm::PointerType *VoidPtrTy;
- llvm::PointerType *Int8PtrTy;
- };
-
- /// void** in address space 0
- union {
- llvm::PointerType *VoidPtrPtrTy;
- llvm::PointerType *Int8PtrPtrTy;
- };
-
- /// The size and alignment of the builtin C type 'int'. This comes
- /// up enough in various ABI lowering tasks to be worth pre-computing.
- union {
- unsigned char IntSizeInBytes;
- unsigned char IntAlignInBytes;
- };
- CharUnits getIntSize() const {
- return CharUnits::fromQuantity(IntSizeInBytes);
- }
- CharUnits getIntAlign() const {
- return CharUnits::fromQuantity(IntAlignInBytes);
- }
-
- /// The width of a pointer into the generic address space.
- unsigned char PointerWidthInBits;
-
- /// The size and alignment of a pointer into the generic address space.
- union {
- unsigned char PointerAlignInBytes;
- unsigned char PointerSizeInBytes;
- unsigned char SizeSizeInBytes; // sizeof(size_t)
- unsigned char SizeAlignInBytes;
- };
- CharUnits getSizeSize() const {
- return CharUnits::fromQuantity(SizeSizeInBytes);
- }
- CharUnits getSizeAlign() const {
- return CharUnits::fromQuantity(SizeAlignInBytes);
- }
- CharUnits getPointerSize() const {
- return CharUnits::fromQuantity(PointerSizeInBytes);
- }
- CharUnits getPointerAlign() const {
- return CharUnits::fromQuantity(PointerAlignInBytes);
- }
-
- llvm::CallingConv::ID RuntimeCC;
- llvm::CallingConv::ID getRuntimeCC() const { return RuntimeCC; }
- llvm::CallingConv::ID BuiltinCC;
- llvm::CallingConv::ID getBuiltinCC() const { return BuiltinCC; }
-};
-
-} // end namespace CodeGen
-} // end namespace clang
-
-#endif
diff --git a/vendors/clang-codegen-private-3.8/CodeGenTypes.h b/vendors/clang-codegen-private-3.8/CodeGenTypes.h
deleted file mode 100644
index a96f23c..0000000
--- a/vendors/clang-codegen-private-3.8/CodeGenTypes.h
+++ /dev/null
@@ -1,335 +0,0 @@
-//===--- CodeGenTypes.h - Type translation for LLVM CodeGen -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This is the code that handles AST -> LLVM type lowering.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_CODEGEN_CODEGENTYPES_H
-#define LLVM_CLANG_LIB_CODEGEN_CODEGENTYPES_H
-
-#include "CGCall.h"
-#include "clang/AST/GlobalDecl.h"
-#include "clang/CodeGen/CGFunctionInfo.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/IR/Module.h"
-#include <vector>
-
-namespace llvm {
-class FunctionType;
-class Module;
-class DataLayout;
-class Type;
-class LLVMContext;
-class StructType;
-}
-
-namespace clang {
-class ABIInfo;
-class ASTContext;
-template <typename> class CanQual;
-class CXXConstructorDecl;
-class CXXDestructorDecl;
-class CXXMethodDecl;
-class CodeGenOptions;
-class FieldDecl;
-class FunctionProtoType;
-class ObjCInterfaceDecl;
-class ObjCIvarDecl;
-class PointerType;
-class QualType;
-class RecordDecl;
-class TagDecl;
-class TargetInfo;
-class Type;
-typedef CanQual<Type> CanQualType;
-
-namespace CodeGen {
-class CGCXXABI;
-class CGRecordLayout;
-class CodeGenModule;
-class RequiredArgs;
-
-enum class StructorType {
- Complete, // constructor or destructor
- Base, // constructor or destructor
- Deleting // destructor only
-};
-
-inline CXXCtorType toCXXCtorType(StructorType T) {
- switch (T) {
- case StructorType::Complete:
- return Ctor_Complete;
- case StructorType::Base:
- return Ctor_Base;
- case StructorType::Deleting:
- llvm_unreachable("cannot have a deleting ctor");
- }
- llvm_unreachable("not a StructorType");
-}
-
-inline StructorType getFromCtorType(CXXCtorType T) {
- switch (T) {
- case Ctor_Complete:
- return StructorType::Complete;
- case Ctor_Base:
- return StructorType::Base;
- case Ctor_Comdat:
- llvm_unreachable("not expecting a COMDAT");
- case Ctor_CopyingClosure:
- case Ctor_DefaultClosure:
- llvm_unreachable("not expecting a closure");
- }
- llvm_unreachable("not a CXXCtorType");
-}
-
-inline CXXDtorType toCXXDtorType(StructorType T) {
- switch (T) {
- case StructorType::Complete:
- return Dtor_Complete;
- case StructorType::Base:
- return Dtor_Base;
- case StructorType::Deleting:
- return Dtor_Deleting;
- }
- llvm_unreachable("not a StructorType");
-}
-
-inline StructorType getFromDtorType(CXXDtorType T) {
- switch (T) {
- case Dtor_Deleting:
- return StructorType::Deleting;
- case Dtor_Complete:
- return StructorType::Complete;
- case Dtor_Base:
- return StructorType::Base;
- case Dtor_Comdat:
- llvm_unreachable("not expecting a COMDAT");
- }
- llvm_unreachable("not a CXXDtorType");
-}
-
-/// This class organizes the cross-module state that is used while lowering
-/// AST types to LLVM types.
-class CodeGenTypes {
- CodeGenModule &CGM;
- // Some of this stuff should probably be left on the CGM.
- ASTContext &Context;
- llvm::Module &TheModule;
- const TargetInfo &Target;
- CGCXXABI &TheCXXABI;
-
- // This should not be moved earlier, since its initialization depends on some
- // of the previous reference members being already initialized
- const ABIInfo &TheABIInfo;
-
- /// The opaque type map for Objective-C interfaces. All direct
- /// manipulation is done by the runtime interfaces, which are
- /// responsible for coercing to the appropriate type; these opaque
- /// types are never refined.
- llvm::DenseMap<const ObjCInterfaceType*, llvm::Type *> InterfaceTypes;
-
- /// Maps clang struct type with corresponding record layout info.
- llvm::DenseMap<const Type*, CGRecordLayout *> CGRecordLayouts;
-
- /// Contains the LLVM IR type for any converted RecordDecl.
- llvm::DenseMap<const Type*, llvm::StructType *> RecordDeclTypes;
-
- /// Hold memoized CGFunctionInfo results.
- llvm::FoldingSet<CGFunctionInfo> FunctionInfos;
-
- /// This set keeps track of records that we're currently converting
- /// to an IR type. For example, when converting:
- /// struct A { struct B { int x; } } when processing 'x', the 'A' and 'B'
- /// types will be in this set.
- llvm::SmallPtrSet<const Type*, 4> RecordsBeingLaidOut;
-
- llvm::SmallPtrSet<const CGFunctionInfo*, 4> FunctionsBeingProcessed;
-
- /// True if we didn't layout a function due to a being inside
- /// a recursive struct conversion, set this to true.
- bool SkippedLayout;
-
- SmallVector<const RecordDecl *, 8> DeferredRecords;
-
- /// This map keeps cache of llvm::Types and maps clang::Type to
- /// corresponding llvm::Type.
- llvm::DenseMap<const Type *, llvm::Type *> TypeCache;
-
-public:
- CodeGenTypes(CodeGenModule &cgm);
- ~CodeGenTypes();
-
- const llvm::DataLayout &getDataLayout() const {
- return TheModule.getDataLayout();
- }
- ASTContext &getContext() const { return Context; }
- const ABIInfo &getABIInfo() const { return TheABIInfo; }
- const TargetInfo &getTarget() const { return Target; }
- CGCXXABI &getCXXABI() const { return TheCXXABI; }
- llvm::LLVMContext &getLLVMContext() { return TheModule.getContext(); }
-
- /// ConvertType - Convert type T into a llvm::Type.
- llvm::Type *ConvertType(QualType T);
-
- /// \brief Converts the GlobalDecl into an llvm::Type. This should be used
- /// when we know the target of the function we want to convert. This is
- /// because some functions (explicitly, those with pass_object_size
- /// parameters) may not have the same signature as their type portrays, and
- /// can only be called directly.
- llvm::Type *ConvertFunctionType(QualType FT,
- const FunctionDecl *FD = nullptr);
-
- /// ConvertTypeForMem - Convert type T into a llvm::Type. This differs from
- /// ConvertType in that it is used to convert to the memory representation for
- /// a type. For example, the scalar representation for _Bool is i1, but the
- /// memory representation is usually i8 or i32, depending on the target.
- llvm::Type *ConvertTypeForMem(QualType T);
-
- /// GetFunctionType - Get the LLVM function type for \arg Info.
- llvm::FunctionType *GetFunctionType(const CGFunctionInfo &Info);
-
- llvm::FunctionType *GetFunctionType(GlobalDecl GD);
-
- /// isFuncTypeConvertible - Utility to check whether a function type can
- /// be converted to an LLVM type (i.e. doesn't depend on an incomplete tag
- /// type).
- bool isFuncTypeConvertible(const FunctionType *FT);
- bool isFuncParamTypeConvertible(QualType Ty);
-
- /// GetFunctionTypeForVTable - Get the LLVM function type for use in a vtable,
- /// given a CXXMethodDecl. If the method to has an incomplete return type,
- /// and/or incomplete argument types, this will return the opaque type.
- llvm::Type *GetFunctionTypeForVTable(GlobalDecl GD);
-
- const CGRecordLayout &getCGRecordLayout(const RecordDecl*);
-
- /// UpdateCompletedType - When we find the full definition for a TagDecl,
- /// replace the 'opaque' type we previously made for it if applicable.
- void UpdateCompletedType(const TagDecl *TD);
-
- /// getNullaryFunctionInfo - Get the function info for a void()
- /// function with standard CC.
- const CGFunctionInfo &arrangeNullaryFunction();
-
- // The arrangement methods are split into three families:
- // - those meant to drive the signature and prologue/epilogue
- // of a function declaration or definition,
- // - those meant for the computation of the LLVM type for an abstract
- // appearance of a function, and
- // - those meant for performing the IR-generation of a call.
- // They differ mainly in how they deal with optional (i.e. variadic)
- // arguments, as well as unprototyped functions.
- //
- // Key points:
- // - The CGFunctionInfo for emitting a specific call site must include
- // entries for the optional arguments.
- // - The function type used at the call site must reflect the formal
- // signature of the declaration being called, or else the call will
- // go awry.
- // - For the most part, unprototyped functions are called by casting to
- // a formal signature inferred from the specific argument types used
- // at the call-site. However, some targets (e.g. x86-64) screw with
- // this for compatibility reasons.
-
- const CGFunctionInfo &arrangeGlobalDeclaration(GlobalDecl GD);
- const CGFunctionInfo &arrangeFunctionDeclaration(const FunctionDecl *FD);
- const CGFunctionInfo &
- arrangeFreeFunctionDeclaration(QualType ResTy, const FunctionArgList &Args,
- const FunctionType::ExtInfo &Info,
- bool isVariadic);
-
- const CGFunctionInfo &arrangeObjCMethodDeclaration(const ObjCMethodDecl *MD);
- const CGFunctionInfo &arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD,
- QualType receiverType);
-
- const CGFunctionInfo &arrangeCXXMethodDeclaration(const CXXMethodDecl *MD);
- const CGFunctionInfo &arrangeCXXStructorDeclaration(const CXXMethodDecl *MD,
- StructorType Type);
- const CGFunctionInfo &arrangeCXXConstructorCall(const CallArgList &Args,
- const CXXConstructorDecl *D,
- CXXCtorType CtorKind,
- unsigned ExtraArgs);
- const CGFunctionInfo &arrangeFreeFunctionCall(const CallArgList &Args,
- const FunctionType *Ty,
- bool ChainCall);
- const CGFunctionInfo &arrangeFreeFunctionCall(QualType ResTy,
- const CallArgList &args,
- FunctionType::ExtInfo info,
- RequiredArgs required);
- const CGFunctionInfo &arrangeBlockFunctionCall(const CallArgList &args,
- const FunctionType *type);
-
- const CGFunctionInfo &arrangeCXXMethodCall(const CallArgList &args,
- const FunctionProtoType *type,
- RequiredArgs required);
- const CGFunctionInfo &arrangeMSMemberPointerThunk(const CXXMethodDecl *MD);
- const CGFunctionInfo &arrangeMSCtorClosure(const CXXConstructorDecl *CD,
- CXXCtorType CT);
- const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionProtoType> Ty,
- const FunctionDecl *FD);
- const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionNoProtoType> Ty);
- const CGFunctionInfo &arrangeCXXMethodType(const CXXRecordDecl *RD,
- const FunctionProtoType *FTP,
- const CXXMethodDecl *MD);
-
- /// "Arrange" the LLVM information for a call or type with the given
- /// signature. This is largely an internal method; other clients
- /// should use one of the above routines, which ultimately defer to
- /// this.
- ///
- /// \param argTypes - must all actually be canonical as params
- const CGFunctionInfo &arrangeLLVMFunctionInfo(CanQualType returnType,
- bool instanceMethod,
- bool chainCall,
- ArrayRef<CanQualType> argTypes,
- FunctionType::ExtInfo info,
- RequiredArgs args);
-
- /// \brief Compute a new LLVM record layout object for the given record.
- CGRecordLayout *ComputeRecordLayout(const RecordDecl *D,
- llvm::StructType *Ty);
-
- /// addRecordTypeName - Compute a name from the given record decl with an
- /// optional suffix and name the given LLVM type using it.
- void addRecordTypeName(const RecordDecl *RD, llvm::StructType *Ty,
- StringRef suffix);
-
-
-public: // These are internal details of CGT that shouldn't be used externally.
- /// ConvertRecordDeclType - Lay out a tagged decl type like struct or union.
- llvm::StructType *ConvertRecordDeclType(const RecordDecl *TD);
-
- /// getExpandedTypes - Expand the type \arg Ty into the LLVM
- /// argument types it would be passed as. See ABIArgInfo::Expand.
- void getExpandedTypes(QualType Ty,
- SmallVectorImpl<llvm::Type *>::iterator &TI);
-
- /// IsZeroInitializable - Return whether a type can be
- /// zero-initialized (in the C++ sense) with an LLVM zeroinitializer.
- bool isZeroInitializable(QualType T);
-
- /// IsZeroInitializable - Return whether a record type can be
- /// zero-initialized (in the C++ sense) with an LLVM zeroinitializer.
- bool isZeroInitializable(const RecordDecl *RD);
-
- bool isRecordLayoutComplete(const Type *Ty) const;
- bool noRecordsBeingLaidOut() const {
- return RecordsBeingLaidOut.empty();
- }
- bool isRecordBeingLaidOut(const Type *Ty) const {
- return RecordsBeingLaidOut.count(Ty);
- }
-
-};
-
-} // end namespace CodeGen
-} // end namespace clang
-
-#endif
diff --git a/vendors/clang-codegen-private-3.8/EHScopeStack.h b/vendors/clang-codegen-private-3.8/EHScopeStack.h
deleted file mode 100644
index 85cd154..0000000
--- a/vendors/clang-codegen-private-3.8/EHScopeStack.h
+++ /dev/null
@@ -1,420 +0,0 @@
-//===-- EHScopeStack.h - Stack for cleanup IR generation --------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// These classes should be the minimum interface required for other parts of
-// CodeGen to emit cleanups. The implementation is in CGCleanup.cpp and other
-// implemenentation details that are not widely needed are in CGCleanup.h.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_CODEGEN_EHSCOPESTACK_H
-#define LLVM_CLANG_LIB_CODEGEN_EHSCOPESTACK_H
-
-#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/IR/BasicBlock.h"
-#include "llvm/IR/Instructions.h"
-#include "llvm/IR/Value.h"
-
-namespace clang {
-namespace CodeGen {
-
-class CodeGenFunction;
-
-/// A branch fixup. These are required when emitting a goto to a
-/// label which hasn't been emitted yet. The goto is optimistically
-/// emitted as a branch to the basic block for the label, and (if it
-/// occurs in a scope with non-trivial cleanups) a fixup is added to
-/// the innermost cleanup. When a (normal) cleanup is popped, any
-/// unresolved fixups in that scope are threaded through the cleanup.
-struct BranchFixup {
- /// The block containing the terminator which needs to be modified
- /// into a switch if this fixup is resolved into the current scope.
- /// If null, LatestBranch points directly to the destination.
- llvm::BasicBlock *OptimisticBranchBlock;
-
- /// The ultimate destination of the branch.
- ///
- /// This can be set to null to indicate that this fixup was
- /// successfully resolved.
- llvm::BasicBlock *Destination;
-
- /// The destination index value.
- unsigned DestinationIndex;
-
- /// The initial branch of the fixup.
- llvm::BranchInst *InitialBranch;
-};
-
-template <class T> struct InvariantValue {
- typedef T type;
- typedef T saved_type;
- static bool needsSaving(type value) { return false; }
- static saved_type save(CodeGenFunction &CGF, type value) { return value; }
- static type restore(CodeGenFunction &CGF, saved_type value) { return value; }
-};
-
-/// A metaprogramming class for ensuring that a value will dominate an
-/// arbitrary position in a function.
-template <class T> struct DominatingValue : InvariantValue<T> {};
-
-template <class T, bool mightBeInstruction =
- std::is_base_of<llvm::Value, T>::value &&
- !std::is_base_of<llvm::Constant, T>::value &&
- !std::is_base_of<llvm::BasicBlock, T>::value>
-struct DominatingPointer;
-template <class T> struct DominatingPointer<T,false> : InvariantValue<T*> {};
-// template <class T> struct DominatingPointer<T,true> at end of file
-
-template <class T> struct DominatingValue<T*> : DominatingPointer<T> {};
-
-enum CleanupKind : unsigned {
- /// Denotes a cleanup that should run when a scope is exited using exceptional
- /// control flow (a throw statement leading to stack unwinding, ).
- EHCleanup = 0x1,
-
- /// Denotes a cleanup that should run when a scope is exited using normal
- /// control flow (falling off the end of the scope, return, goto, ...).
- NormalCleanup = 0x2,
-
- NormalAndEHCleanup = EHCleanup | NormalCleanup,
-
- InactiveCleanup = 0x4,
- InactiveEHCleanup = EHCleanup | InactiveCleanup,
- InactiveNormalCleanup = NormalCleanup | InactiveCleanup,
- InactiveNormalAndEHCleanup = NormalAndEHCleanup | InactiveCleanup
-};
-
-/// A stack of scopes which respond to exceptions, including cleanups
-/// and catch blocks.
-class EHScopeStack {
-public:
- /* Should switch to alignof(uint64_t) instead of 8, when EHCleanupScope can */
- enum { ScopeStackAlignment = 8 };
-
- /// A saved depth on the scope stack. This is necessary because
- /// pushing scopes onto the stack invalidates iterators.
- class stable_iterator {
- friend class EHScopeStack;
-
- /// Offset from StartOfData to EndOfBuffer.
- ptrdiff_t Size;
-
- stable_iterator(ptrdiff_t Size) : Size(Size) {}
-
- public:
- static stable_iterator invalid() { return stable_iterator(-1); }
- stable_iterator() : Size(-1) {}
-
- bool isValid() const { return Size >= 0; }
-
- /// Returns true if this scope encloses I.
- /// Returns false if I is invalid.
- /// This scope must be valid.
- bool encloses(stable_iterator I) const { return Size <= I.Size; }
-
- /// Returns true if this scope strictly encloses I: that is,
- /// if it encloses I and is not I.
- /// Returns false is I is invalid.
- /// This scope must be valid.
- bool strictlyEncloses(stable_iterator I) const { return Size < I.Size; }
-
- friend bool operator==(stable_iterator A, stable_iterator B) {
- return A.Size == B.Size;
- }
- friend bool operator!=(stable_iterator A, stable_iterator B) {
- return A.Size != B.Size;
- }
- };
-
- /// Information for lazily generating a cleanup. Subclasses must be
- /// POD-like: cleanups will not be destructed, and they will be
- /// allocated on the cleanup stack and freely copied and moved
- /// around.
- ///
- /// Cleanup implementations should generally be declared in an
- /// anonymous namespace.
- class Cleanup {
- // Anchor the construction vtable.
- virtual void anchor();
-
- protected:
- ~Cleanup() = default;
-
- public:
- Cleanup(const Cleanup &) = default;
- Cleanup(Cleanup &&) {}
- Cleanup() = default;
-
- /// Generation flags.
- class Flags {
- enum {
- F_IsForEH = 0x1,
- F_IsNormalCleanupKind = 0x2,
- F_IsEHCleanupKind = 0x4
- };
- unsigned flags;
-
- public:
- Flags() : flags(0) {}
-
- /// isForEH - true if the current emission is for an EH cleanup.
- bool isForEHCleanup() const { return flags & F_IsForEH; }
- bool isForNormalCleanup() const { return !isForEHCleanup(); }
- void setIsForEHCleanup() { flags |= F_IsForEH; }
-
- bool isNormalCleanupKind() const { return flags & F_IsNormalCleanupKind; }
- void setIsNormalCleanupKind() { flags |= F_IsNormalCleanupKind; }
-
- /// isEHCleanupKind - true if the cleanup was pushed as an EH
- /// cleanup.
- bool isEHCleanupKind() const { return flags & F_IsEHCleanupKind; }
- void setIsEHCleanupKind() { flags |= F_IsEHCleanupKind; }
- };
-
-
- /// Emit the cleanup. For normal cleanups, this is run in the
- /// same EH context as when the cleanup was pushed, i.e. the
- /// immediately-enclosing context of the cleanup scope. For
- /// EH cleanups, this is run in a terminate context.
- ///
- // \param flags cleanup kind.
- virtual void Emit(CodeGenFunction &CGF, Flags flags) = 0;
- };
-
- /// ConditionalCleanup stores the saved form of its parameters,
- /// then restores them and performs the cleanup.
- template <class T, class... As>
- class ConditionalCleanup final : public Cleanup {
- typedef std::tuple<typename DominatingValue<As>::saved_type...> SavedTuple;
- SavedTuple Saved;
-
- template <std::size_t... Is>
- T restore(CodeGenFunction &CGF, llvm::index_sequence<Is...>) {
- // It's important that the restores are emitted in order. The braced init
- // list guarentees that.
- return T{DominatingValue<As>::restore(CGF, std::get<Is>(Saved))...};
- }
-
- void Emit(CodeGenFunction &CGF, Flags flags) override {
- restore(CGF, llvm::index_sequence_for<As...>()).Emit(CGF, flags);
- }
-
- public:
- ConditionalCleanup(typename DominatingValue<As>::saved_type... A)
- : Saved(A...) {}
-
- ConditionalCleanup(SavedTuple Tuple) : Saved(std::move(Tuple)) {}
- };
-
-private:
- // The implementation for this class is in CGException.h and
- // CGException.cpp; the definition is here because it's used as a
- // member of CodeGenFunction.
-
- /// The start of the scope-stack buffer, i.e. the allocated pointer
- /// for the buffer. All of these pointers are either simultaneously
- /// null or simultaneously valid.
- char *StartOfBuffer;
-
- /// The end of the buffer.
- char *EndOfBuffer;
-
- /// The first valid entry in the buffer.
- char *StartOfData;
-
- /// The innermost normal cleanup on the stack.
- stable_iterator InnermostNormalCleanup;
-
- /// The innermost EH scope on the stack.
- stable_iterator InnermostEHScope;
-
- /// The current set of branch fixups. A branch fixup is a jump to
- /// an as-yet unemitted label, i.e. a label for which we don't yet
- /// know the EH stack depth. Whenever we pop a cleanup, we have
- /// to thread all the current branch fixups through it.
- ///
- /// Fixups are recorded as the Use of the respective branch or
- /// switch statement. The use points to the final destination.
- /// When popping out of a cleanup, these uses are threaded through
- /// the cleanup and adjusted to point to the new cleanup.
- ///
- /// Note that branches are allowed to jump into protected scopes
- /// in certain situations; e.g. the following code is legal:
- /// struct A { ~A(); }; // trivial ctor, non-trivial dtor
- /// goto foo;
- /// A a;
- /// foo:
- /// bar();
- SmallVector<BranchFixup, 8> BranchFixups;
-
- char *allocate(size_t Size);
- void deallocate(size_t Size);
-
- void *pushCleanup(CleanupKind K, size_t DataSize);
-
-public:
- EHScopeStack() : StartOfBuffer(nullptr), EndOfBuffer(nullptr),
- StartOfData(nullptr), InnermostNormalCleanup(stable_end()),
- InnermostEHScope(stable_end()) {}
- ~EHScopeStack() { delete[] StartOfBuffer; }
-
- /// Push a lazily-created cleanup on the stack.
- template <class T, class... As> void pushCleanup(CleanupKind Kind, As... A) {
- static_assert(llvm::AlignOf<T>::Alignment <= ScopeStackAlignment,
- "Cleanup's alignment is too large.");
- void *Buffer = pushCleanup(Kind, sizeof(T));
- Cleanup *Obj = new (Buffer) T(A...);
- (void) Obj;
- }
-
- /// Push a lazily-created cleanup on the stack. Tuple version.
- template <class T, class... As>
- void pushCleanupTuple(CleanupKind Kind, std::tuple<As...> A) {
- static_assert(llvm::AlignOf<T>::Alignment <= ScopeStackAlignment,
- "Cleanup's alignment is too large.");
- void *Buffer = pushCleanup(Kind, sizeof(T));
- Cleanup *Obj = new (Buffer) T(std::move(A));
- (void) Obj;
- }
-
- // Feel free to add more variants of the following:
-
- /// Push a cleanup with non-constant storage requirements on the
- /// stack. The cleanup type must provide an additional static method:
- /// static size_t getExtraSize(size_t);
- /// The argument to this method will be the value N, which will also
- /// be passed as the first argument to the constructor.
- ///
- /// The data stored in the extra storage must obey the same
- /// restrictions as normal cleanup member data.
- ///
- /// The pointer returned from this method is valid until the cleanup
- /// stack is modified.
- template <class T, class... As>
- T *pushCleanupWithExtra(CleanupKind Kind, size_t N, As... A) {
- static_assert(llvm::AlignOf<T>::Alignment <= ScopeStackAlignment,
- "Cleanup's alignment is too large.");
- void *Buffer = pushCleanup(Kind, sizeof(T) + T::getExtraSize(N));
- return new (Buffer) T(N, A...);
- }
-
- void pushCopyOfCleanup(CleanupKind Kind, const void *Cleanup, size_t Size) {
- void *Buffer = pushCleanup(Kind, Size);
- std::memcpy(Buffer, Cleanup, Size);
- }
-
- /// Pops a cleanup scope off the stack. This is private to CGCleanup.cpp.
- void popCleanup();
-
- /// Push a set of catch handlers on the stack. The catch is
- /// uninitialized and will need to have the given number of handlers
- /// set on it.
- class EHCatchScope *pushCatch(unsigned NumHandlers);
-
- /// Pops a catch scope off the stack. This is private to CGException.cpp.
- void popCatch();
-
- /// Push an exceptions filter on the stack.
- class EHFilterScope *pushFilter(unsigned NumFilters);
-
- /// Pops an exceptions filter off the stack.
- void popFilter();
-
- /// Push a terminate handler on the stack.
- void pushTerminate();
-
- /// Pops a terminate handler off the stack.
- void popTerminate();
-
- // Returns true iff the current scope is either empty or contains only
- // lifetime markers, i.e. no real cleanup code
- bool containsOnlyLifetimeMarkers(stable_iterator Old) const;
-
- /// Determines whether the exception-scopes stack is empty.
- bool empty() const { return StartOfData == EndOfBuffer; }
-
- bool requiresLandingPad() const {
- return InnermostEHScope != stable_end();
- }
-
- /// Determines whether there are any normal cleanups on the stack.
- bool hasNormalCleanups() const {
- return InnermostNormalCleanup != stable_end();
- }
-
- /// Returns the innermost normal cleanup on the stack, or
- /// stable_end() if there are no normal cleanups.
- stable_iterator getInnermostNormalCleanup() const {
- return InnermostNormalCleanup;
- }
- stable_iterator getInnermostActiveNormalCleanup() const;
-
- stable_iterator getInnermostEHScope() const {
- return InnermostEHScope;
- }
-
-
- /// An unstable reference to a scope-stack depth. Invalidated by
- /// pushes but not pops.
- class iterator;
-
- /// Returns an iterator pointing to the innermost EH scope.
- iterator begin() const;
-
- /// Returns an iterator pointing to the outermost EH scope.
- iterator end() const;
-
- /// Create a stable reference to the top of the EH stack. The
- /// returned reference is valid until that scope is popped off the
- /// stack.
- stable_iterator stable_begin() const {
- return stable_iterator(EndOfBuffer - StartOfData);
- }
-
- /// Create a stable reference to the bottom of the EH stack.
- static stable_iterator stable_end() {
- return stable_iterator(0);
- }
-
- /// Translates an iterator into a stable_iterator.
- stable_iterator stabilize(iterator it) const;
-
- /// Turn a stable reference to a scope depth into a unstable pointer
- /// to the EH stack.
- iterator find(stable_iterator save) const;
-
- /// Add a branch fixup to the current cleanup scope.
- BranchFixup &addBranchFixup() {
- assert(hasNormalCleanups() && "adding fixup in scope without cleanups");
- BranchFixups.push_back(BranchFixup());
- return BranchFixups.back();
- }
-
- unsigned getNumBranchFixups() const { return BranchFixups.size(); }
- BranchFixup &getBranchFixup(unsigned I) {
- assert(I < getNumBranchFixups());
- return BranchFixups[I];
- }
-
- /// Pops lazily-removed fixups from the end of the list. This
- /// should only be called by procedures which have just popped a
- /// cleanup or resolved one or more fixups.
- void popNullFixups();
-
- /// Clears the branch-fixups list. This should only be called by
- /// ResolveAllBranchFixups.
- void clearFixups() { BranchFixups.clear(); }
-};
-
-} // namespace CodeGen
-} // namespace clang
-
-#endif
diff --git a/vendors/clang-codegen-private-3.8/SanitizerMetadata.h b/vendors/clang-codegen-private-3.8/SanitizerMetadata.h
deleted file mode 100644
index 166f0e6..0000000
--- a/vendors/clang-codegen-private-3.8/SanitizerMetadata.h
+++ /dev/null
@@ -1,53 +0,0 @@
-//===--- SanitizerMetadata.h - Metadata for sanitizers ----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Class which emits metadata consumed by sanitizer instrumentation passes.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_LIB_CODEGEN_SANITIZERMETADATA_H
-#define LLVM_CLANG_LIB_CODEGEN_SANITIZERMETADATA_H
-
-#include "clang/AST/Type.h"
-#include "clang/Basic/LLVM.h"
-#include "clang/Basic/SourceLocation.h"
-
-namespace llvm {
-class GlobalVariable;
-class Instruction;
-class MDNode;
-}
-
-namespace clang {
-class VarDecl;
-
-namespace CodeGen {
-
-class CodeGenModule;
-
-class SanitizerMetadata {
- SanitizerMetadata(const SanitizerMetadata &) = delete;
- void operator=(const SanitizerMetadata &) = delete;
-
- CodeGenModule &CGM;
-public:
- SanitizerMetadata(CodeGenModule &CGM);
- void reportGlobalToASan(llvm::GlobalVariable *GV, const VarDecl &D,
- bool IsDynInit = false);
- void reportGlobalToASan(llvm::GlobalVariable *GV, SourceLocation Loc,
- StringRef Name, QualType Ty, bool IsDynInit = false,
- bool IsBlacklisted = false);
- void disableSanitizerForGlobal(llvm::GlobalVariable *GV);
- void disableSanitizerForInstruction(llvm::Instruction *I);
-private:
- llvm::MDNode *getLocationMetadata(SourceLocation Loc);
-};
-} // end namespace CodeGen
-} // end namespace clang
-
-#endif

Event Timeline