Skip to content

Commit

Permalink
Merge branch 'sotoc-new-variable-handling' into 'aurora_offloading_pr…
Browse files Browse the repository at this point in the history
…ototype'

New (and hopefully correct) Variable Handling for Sotoc

Closes llvm#51

See merge request NEC-RWTH-Projects/clang!30
  • Loading branch information
manorom committed Oct 29, 2019
2 parents b0d9820 + e9aba95 commit 9456673
Show file tree
Hide file tree
Showing 10 changed files with 429 additions and 352 deletions.
1 change: 1 addition & 0 deletions clang/tools/sotoc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ set(USE_CLANG_LIBS clangFrontend
set(SOTOC_SOURCES src/main.cpp
src/TargetCode.cpp
src/TargetCodeFragment.cpp
src/TargetRegionVariable.cpp
src/Visitors.cpp
src/DeclResolver.cpp
src/OmpPragma.cpp)
Expand Down
2 changes: 1 addition & 1 deletion clang/tools/sotoc/src/OmpPragma.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class OmpPragma {

public:
OmpPragma(TargetCodeRegion *TCR)
: PP(TCR->getPP()), Clauses(*TCR->getOMPClauses()),
: PP(TCR->getPP()), Clauses(TCR->getOMPClauses()),
Kind(TCR->getTargetCodeKind()){};
OmpPragma(clang::OMPExecutableDirective *Directive, clang::PrintingPolicy PP)
: PP(PP), Clauses(Directive->clauses()),
Expand Down
233 changes: 79 additions & 154 deletions clang/tools/sotoc/src/TargetCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,112 +108,104 @@ void TargetCode::generateFunctionPrologue(TargetCodeRegion *TCR,
std::string elemType;
bool first = true;
Out << "void " << generateFunctionName(TCR) << "(";
for (auto i = TCR->getCapturedVarsBegin(), e = TCR->getCapturedVarsEnd();
i != e; ++i) {
std::string VarName = (*i)->getDeclName().getAsString();
auto C = TCR->GetReferredOMPClause(*i);

for (auto &Var : TCR->capturedVars()) {
if (!first) {
Out << ", ";
}
first = false;

// check for constant or variable length arrays, because of
// AST representation and naive getType
if (auto t = clang::dyn_cast_or_null<clang::ArrayType>(
(*i)->getType().getTypePtr())) {
DEBUGP("Generating code for array type");
int dim = 0;

std::vector<int> VariableDimensions;
handleArrays(&t, DimString, dim, VariableDimensions, TCR, elemType,
VarName);

for (int d : VariableDimensions) {
Out << "unsigned long long __sotoc_vla_dim" << d << "_" << VarName
if (Var.isArray()) {
for (const unsigned int &d : Var.variabledSizedArrayDimensions()) {
Out << "unsigned long long __sotoc_vla_dim" << d << "_" << Var.name()
<< ", ";
}
}
// Because arrays are passed by reference and (for our purposes) their type
// is 'void', the rest of their handling ist the same as for scalars.
if (Var.isArray()) {
Out << "void ";
} else {
Out << Var.typeName() << " ";
}

// set type to void* to avoid warnings from the compiler
Out << "void *__sotoc_var_";
nDim.push_back(dim); // push total number of dimensions
if (Var.passedByPointer()) {
Out << "*__sotoc_var_";
}
Out << Var.name();
}

for (auto *ClauseVar : TCR->ompClausesParams()) {
if (!first) {
Out << ", ";
} else {
Out << (*i)->getType().getAsString() << " ";
if (!(*i)->getType().getTypePtr()->isPointerType()) {
if (C) {
// Parameters which are not first private (e.g., explicit mapped vars)
// are passed by reference, all others by value.
if (C->getClauseKind() !=
clang::OpenMPClauseKind::OMPC_firstprivate &&
C->getClauseKind() !=
clang::OpenMPClauseKind::OMPC_private &&
C->getClauseKind() !=
clang::OpenMPClauseKind::OMPC_depend) {
Out << "*__sotoc_var_";
}
}
first = false;
}

// TODO: this is the same code as in TargetRegionVariable.cpp, so we might
// want to deduplicated this.
auto *ClauseVarType = ClauseVar->getType().getTypePtr();
if (auto *AT = llvm::dyn_cast<clang::ArrayType>(ClauseVarType)) {
while (auto *NAT = llvm::dyn_cast<clang::ArrayType>(AT->getElementType().getTypePtr())) {
AT = NAT;
}
Out << AT->getElementType().getAsString() << " *";
} else {
Out << ClauseVar->getType().getAsString() << " ";
}
Out << VarName;
Out << ClauseVar->getName();
}

Out << ")\n{\n";

// bring captured scalars into scope
for (auto I = TCR->getCapturedVarsBegin(), E = TCR->getCapturedVarsEnd();
I != E; ++I) {
auto C = TCR->GetReferredOMPClause(*I);
// again check for constant and variable-length arrays
if (auto t = clang::dyn_cast_or_null<clang::ArrayType>(
(*I)->getType().getTypePtr())) {
auto VarName = (*I)->getDeclName().getAsString();

do {
t = clang::dyn_cast_or_null<clang::ArrayType>(
t->getElementType().getTypePtr());
} while (t != NULL);

Out << " " << elemType << " (*" << VarName << ")";

// Get number of Dimensions(nDim) and write sizes(DimString)
for (int i = 1; i < nDim.front(); i++) {
DimString.pop_front();
Out << "[" << DimString.front() << "]";
}
DimString.pop_front(); // remove last size
nDim.pop_front(); // remove number of dimensions of last variable

Out << " = __sotoc_var_" << VarName << ";\n";

auto LowerBound = TCR->CapturedLowerBounds.find(*I);
if (LowerBound != TCR->CapturedLowerBounds.end()) {
Out << VarName << " = " << VarName << " - (";
LowerBound->second->printPretty(Out, NULL, TCR->getPP());
Out << ");\n";
}

} else {
if (!(*I)->getType().getTypePtr()->isPointerType()) {
if (C) {
// Parameters which are not first private (e.g., explicit mapped vars)
// are passed by reference, all others by value.
if (C->getClauseKind() !=
clang::OpenMPClauseKind::OMPC_firstprivate &&
C->getClauseKind() !=
clang::OpenMPClauseKind::OMPC_private &&
C->getClauseKind() !=
clang::OpenMPClauseKind::OMPC_depend) {
auto VarName = (*I)->getDeclName().getAsString();
Out << " " << (*I)->getType().getAsString() << " " << VarName
<< " = "
<< "*__sotoc_var_" << VarName << ";\n";
for (auto &Var : TCR->capturedVars()) {
// Ignore everything not passed by reference here
if (Var.passedByPointer()) {
// Handle multi-dimensional arrays
if (Var.isArray()) {
// Declare the arrays as a pointer. This way we can assign it a pointer
// However, this also means we have to ignore the first array
// dimension.
Out << " " << Var.typeName() << " (*" << Var.name() << ")";

// For every array dimension other then the first: declare them by
// adding the array brackets ('[', ']') to the declaration. Also add
// the size of this dimension if we have it.
bool first = true;
for (auto &dimensionSize: Var.arrayDimensionSizes()) {
//We need to discard the first element
if (first) {
first = false;
continue;
}
Out << "[" << dimensionSize << "]";
}
// After we have declare the array, we also need to assign it.
// We may also have to adjust the array bounds if we only get a slice
// of the array (in the first dimesion. All other dimensions should
// not require adjustment as their slicing is ignored)
Out << " = __sotoc_var_" << Var.name() << ";\n";
// Move the bounds if we have a slice
auto LowerBound = Var.arrayLowerBound();
if (LowerBound.hasValue()) {
Out << " " << Var.name() << " = " << Var.name() << " - ";
LowerBound.getValue()->printPretty(Out, NULL, TCR->getPP());
Out << ";\n";
}
} else {
// Handle all other types passed by reference
Out << Var.typeName() << " " << Var.name() << " = "
<< "*__sotoc_var_" << Var.name() << ";\n";
}
}
}
Out << "\n";

// Generate local declarations.
Out << TCR->PrintLocalVarsFromClauses();
for (auto *privateVar: TCR->privateVars()) {
Out << " " << privateVar->getType().getAsString() << " "
<< privateVar->getName() << ";\n";
}

// The runtime can decide to only create one team.
// Therfore, replace target teams constructs.
Expand All @@ -235,31 +227,9 @@ void TargetCode::generateFunctionEpilogue(TargetCodeRegion *TCR,

Out << "\n";
// copy values from scalars from scoped vars back into pointers
for (auto I = TCR->getCapturedVarsBegin(), E = TCR->getCapturedVarsEnd();
I != E; ++I) {
auto C = TCR->GetReferredOMPClause(*I);

// if array then already pointer
if (auto t = clang::dyn_cast_or_null<clang::ArrayType>(
(*I)->getType().getTypePtr())) {
auto VarName = (*I)->getDeclName().getAsString();
Out << "\n __sotoc_var_" << VarName << " = " << VarName << ";";
} else {
if (!(*I)->getType().getTypePtr()->isPointerType()) {
if (C) {
// Parameters which are not first private (e.g., explicit mapped vars)
// are passed by reference, all others by value.
if (C->getClauseKind() !=
clang::OpenMPClauseKind::OMPC_firstprivate &&
C->getClauseKind() !=
clang::OpenMPClauseKind::OMPC_private &&
C->getClauseKind() !=
clang::OpenMPClauseKind::OMPC_depend) {
auto VarName = (*I)->getDeclName().getAsString();
Out << "\n *__sotoc_var_" << VarName << " = " << VarName << ";";
}
}
}
for (auto &Var : TCR->capturedVars()) {
if (Var.passedByPointer() && !Var.isArray()) {
Out << "\n *__sotoc_var_" << Var.name() << " = " << Var.name() << ";";
}
}

Expand All @@ -283,48 +253,3 @@ std::string TargetCode::generateFunctionName(TargetCodeRegion *TCR) {
<< LineNum;
return FunctionName;
}

void TargetCode::handleArrays(const clang::ArrayType **t,
std::list<std::string> &DimString, int &dim,
std::vector<int> &VariableDims,
TargetCodeRegion *TCR, std::string &elemType,
const std::string &ArrayName) {
auto OrigT = *t;

if (!t) {
return;
} else {
// We just remember the last element type
elemType = OrigT->getElementType().getAsString();
DEBUGP("The last QualType of the array is: " + elemType);
}

if (auto t1 = clang::dyn_cast_or_null<clang::ConstantArrayType>(OrigT)) {
DEBUGP("ArrayType is CAT");
DimString.push_back(t1->getSize().toString(10, false));
++dim;

} else if (auto t1 =
clang::dyn_cast_or_null<clang::VariableArrayType>(OrigT)) {
DEBUGP("ArrayType VAT");
std::string PrettyStr = "";
llvm::raw_string_ostream PrettyOS(PrettyStr);
PrettyOS << "__sotoc_vla_dim" << dim << "_" << ArrayName;
DimString.push_back(PrettyOS.str());
VariableDims.push_back(dim);
++dim;

} else {
DEBUGP("No more array dimensions");
// Restore t if we dont have an array type anymore
*t = OrigT;
return;
}

(*t) = clang::dyn_cast_or_null<clang::ArrayType>(
OrigT->getElementType().getTypePtr());
if (*t) {
// Recursively handle all dimensions
handleArrays(t, DimString, dim, VariableDims, TCR, elemType, ArrayName);
}
}
13 changes: 0 additions & 13 deletions clang/tools/sotoc/src/TargetCode.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,4 @@ class TargetCode {
void generateFunctionEpilogue(TargetCodeRegion *TCR, llvm::raw_ostream &Out);
/// Generate a function name for a target region.
std::string generateFunctionName(TargetCodeRegion *TCR);

/// This function recursively handles constant and variable-length array types
/// and any mixed forms. Incomplete array types are not supported at the
/// moment.
/// \param t The (n-dimensional) array
/// \param DimString A list of string which returns one entry per dimension
/// \param dim The dimension count
/// \param TCR The target code region
/// \param returns the last element type (i.e., the type of the array)
void handleArrays(const clang::ArrayType **t,
std::list<std::string> &DimString, int &dim,
std::vector<int> &VariableDimensions, TargetCodeRegion *TCR,
std::string &elemType, const std::string &ArrayName);
};
Loading

0 comments on commit 9456673

Please sign in to comment.