Skip to content

Target profile #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticDriverKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -654,4 +654,7 @@ def warn_drv_fjmc_for_elf_only : Warning<
def err_drv_target_variant_invalid : Error<
"unsupported '%0' value '%1'; use 'ios-macabi' instead">;

def err_drv_invalid_directx_shader_module : Error<
"invalid profile : %0">;

}
6 changes: 5 additions & 1 deletion clang/include/clang/Driver/Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ class Driver {
GXXMode,
CPPMode,
CLMode,
FlangMode
FlangMode,
DXCMode
} Mode;

enum SaveTempsMode {
Expand Down Expand Up @@ -195,6 +196,9 @@ class Driver {
/// Other modes fall back to calling gcc which in turn calls gfortran.
bool IsFlangMode() const { return Mode == FlangMode; }

/// Whether the driver should follow dxc.exe like behavior.
bool IsDXCMode() const { return Mode == DXCMode; }

/// Only print tool bindings, don't build any jobs.
unsigned CCCPrintBindings : 1;

Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Driver/Options.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ enum ClangFlags {
FlangOption = (1 << 14),
FC1Option = (1 << 15),
FlangOnlyOption = (1 << 16),
Ignored = (1 << 17),
DXCOption = (1 << 17),
Ignored = (1 << 18),
};

enum ID {
Expand Down
34 changes: 34 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ def CC1Option : OptionFlag;
// CC1AsOption - This option should be accepted by clang -cc1as.
def CC1AsOption : OptionFlag;

// DXCOption - This is a dxc.exe compatibility option. Options with this flag
// are made available when the driver is running in DXC compatibility mode.
def DXCOption : OptionFlag;

// NoDriverOption - This option should not be accepted by the driver.
def NoDriverOption : OptionFlag;

Expand Down Expand Up @@ -6641,3 +6645,33 @@ def _SLASH_Ze : CLFlag<"Ze">;
def _SLASH_Zg : CLFlag<"Zg">;
def _SLASH_ZI : CLFlag<"ZI">;
def _SLASH_ZW : CLJoined<"ZW">;

//===----------------------------------------------------------------------===//
// clang-dxc Options
//===----------------------------------------------------------------------===//

def dxc_Group : OptionGroup<"<clang-dxc options>">, Flags<[DXCOption]>,
HelpText<"dxc compatibility options">;

class DXCJoinedOrSeparate<string name> : Option<["/", "-"], name,
KIND_JOINED_OR_SEPARATE>, Group<dxc_Group>, Flags<[DXCOption, NoXarchOption]>;

def dxc_help : Option<["/", "-", "--"], "help", KIND_JOINED>,
Group<dxc_Group>, Flags<[DXCOption, NoXarchOption]>, Alias<help>,
HelpText<"Display available options">;


def Fo : DXCJoinedOrSeparate<"Fo">, Alias<o>,
HelpText<"Output object file.">;

def target_profile : DXCJoinedOrSeparate<"T">, MetaVarName<"<profile>">,
HelpText<"Set target profile.">,
Values<"ps_6_0, ps_6_1, ps_6_2, ps_6_3, ps_6_4, ps_6_5, ps_6_6, ps_6_7,"
"vs_6_0, vs_6_1, vs_6_2, vs_6_3, vs_6_4, vs_6_5, vs_6_6, vs_6_7,"
"gs_6_0, gs_6_1, gs_6_2, gs_6_3, gs_6_4, gs_6_5, gs_6_6, gs_6_7,"
"hs_6_0, hs_6_1, hs_6_2, hs_6_3, hs_6_4, hs_6_5, hs_6_6, hs_6_7,"
"ds_6_0, ds_6_1, ds_6_2, ds_6_3, ds_6_4, ds_6_5, ds_6_6, ds_6_7,"
"cs_6_0, cs_6_1, cs_6_2, cs_6_3, cs_6_4, cs_6_5, cs_6_6, cs_6_7,"
"lib_6_3, lib_6_4, lib_6_5, lib_6_6, lib_6_7, lib_6_x,"
"ms_6_5, ms_6_6, ms_6_7,"
"as_6_5, as_6_6, as_6_7">;
1 change: 1 addition & 0 deletions clang/lib/Driver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ add_clang_library(clangDriver
ToolChains/HIPAMD.cpp
ToolChains/HIPSPV.cpp
ToolChains/Hexagon.cpp
ToolChains/HLSL.cpp
ToolChains/Hurd.cpp
ToolChains/Linux.cpp
ToolChains/MipsLinux.cpp
Expand Down
22 changes: 21 additions & 1 deletion clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "ToolChains/HIPSPV.h"
#include "ToolChains/Haiku.h"
#include "ToolChains/Hexagon.h"
#include "ToolChains/HLSL.h"
#include "ToolChains/Hurd.h"
#include "ToolChains/Lanai.h"
#include "ToolChains/Linux.h"
Expand Down Expand Up @@ -231,6 +232,7 @@ void Driver::setDriverMode(StringRef Value) {
.Case("cpp", CPPMode)
.Case("cl", CLMode)
.Case("flang", FlangMode)
.Case("dxc", DXCMode)
.Default(None))
Mode = *M;
else
Expand Down Expand Up @@ -1190,6 +1192,15 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
T.setObjectFormat(llvm::Triple::COFF);
TargetTriple = T.str();
}

if (IsDXCMode()) {
// clang-dxc target is build from target_profile option.
// Just set OS to shader model to select HLSLToolChain.
llvm::Triple T(TargetTriple);
T.setOS(llvm::Triple::ShaderModel);
TargetTriple = T.str();
}

if (const Arg *A = Args.getLastArg(options::OPT_target))
TargetTriple = A->getValue();
if (const Arg *A = Args.getLastArg(options::OPT_ccc_install_dir))
Expand Down Expand Up @@ -5680,6 +5691,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::ZOS:
TC = std::make_unique<toolchains::ZOS>(*this, Target, Args);
break;
case llvm::Triple::ShaderModel:
TC = std::make_unique<toolchains::HLSLToolChain>(*this, Target, Args);
break;
default:
// Of these targets, Hexagon is the only one that might have
// an OS of Linux, in which case it got handled above already.
Expand Down Expand Up @@ -5895,7 +5909,13 @@ Driver::getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const {
} else {
ExcludedFlagsBitmask |= options::CLOption;
}

if (IsDXCMode()) {
// Include DXC and Core options.
IncludedFlagsBitmask |= options::DXCOption;
IncludedFlagsBitmask |= options::CoreOption;
} else {
ExcludedFlagsBitmask |= options::DXCOption;
}
return std::make_pair(IncludedFlagsBitmask, ExcludedFlagsBitmask);
}

Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/ToolChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {
{"cl", "--driver-mode=cl"},
{"++", "--driver-mode=g++"},
{"flang", "--driver-mode=flang"},
{"clang-dxc", "--driver-mode=dxc"},
};

for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i) {
Expand Down
147 changes: 147 additions & 0 deletions clang/lib/Driver/ToolChains/HLSL.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
//===--- HLSL.cpp - HLSL ToolChain Implementations --------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "HLSL.h"
#include "CommonArgs.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"

using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang::driver::toolchains;
using namespace clang;
using namespace llvm::opt;
using namespace llvm;

namespace {

const unsigned OfflineLibMinor = 0xF;
const unsigned MaxShaderModel6Minor = 7;

bool isLegalVersion(VersionTuple Version, unsigned Major, unsigned MinMinor,
unsigned MaxMinor) {
VersionTuple Min(Major, MinMinor);
VersionTuple Max(Major, MaxMinor);
return Min <= Version && Version <= Max;
}

bool isLegalShaderModel(Triple &T) {
if (T.getOS() != Triple::OSType::ShaderModel)
return false;

auto Version = T.getOSVersion();
if (Version.getBuild())
return false;
if (Version.getSubminor())
return false;
if (!Version.getMinor())
return false;

auto Kind = T.getEnvironment();

switch (Kind) {
default:
return false;
case Triple::EnvironmentType::Vertex:
case Triple::EnvironmentType::Hull:
case Triple::EnvironmentType::Domain:
case Triple::EnvironmentType::Geometry:
case Triple::EnvironmentType::Pixel:
case Triple::EnvironmentType::Compute: {
if (isLegalVersion(Version, 4, 0, 1))
return true;
if (isLegalVersion(Version, 5, 0, 1))
return true;

if (isLegalVersion(Version, 6, 0, MaxShaderModel6Minor))
return true;
} break;
case Triple::EnvironmentType::Library: {
VersionTuple SM6x(6, OfflineLibMinor);
if (Version == SM6x)
return true;
if (isLegalVersion(Version, 6, 3, MaxShaderModel6Minor))
return true;
} break;
case Triple::EnvironmentType::Amplification:
case Triple::EnvironmentType::Mesh: {
if (isLegalVersion(Version, 6, 5, MaxShaderModel6Minor))
return true;
} break;
}
return false;
}

std::string tryParseProfile(StringRef Profile) {
// [ps|vs|gs|hs|ds|cs|ms|as]_[major]_[minor]
SmallVector<StringRef, 3> Parts;
Profile.split(Parts, "_");
if (Parts.size() != 3)
return "";

Triple::EnvironmentType Kind =
StringSwitch<Triple::EnvironmentType>(Parts[0])
.Case("ps", Triple::EnvironmentType::Pixel)
.Case("vs", Triple::EnvironmentType::Vertex)
.Case("gs", Triple::EnvironmentType::Geometry)
.Case("hs", Triple::EnvironmentType::Hull)
.Case("ds", Triple::EnvironmentType::Domain)
.Case("cs", Triple::EnvironmentType::Compute)
.Case("lib", Triple::EnvironmentType::Library)
.Case("ms", Triple::EnvironmentType::Mesh)
.Case("as", Triple::EnvironmentType::Amplification)
.Default(Triple::EnvironmentType::UnknownEnvironment);
if (Kind == Triple::EnvironmentType::UnknownEnvironment)
return "";

unsigned long long Major = 0;
if (llvm::getAsUnsignedInteger(Parts[1], 0, Major))
return "";

unsigned long long Minor = 0;
if (Parts[2] == "x")
Minor = OfflineLibMinor;
else if (llvm::getAsUnsignedInteger(Parts[2], 0, Minor))
return "";

// dxil-unknown-shadermodel-hull
llvm::Triple T;
T.setArch(Triple::ArchType::dxil);
T.setOSName(Triple::getOSTypeName(Triple::OSType::ShaderModel).str() +
VersionTuple(Major, Minor).getAsString());
T.setEnvironment(Kind);
if (isLegalShaderModel(T))
return T.getTriple();
else
return "";
}

} // namespace

/// DirectX Toolchain
HLSLToolChain::HLSLToolChain(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args) {}

std::string
HLSLToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
types::ID InputType) const {
if (Arg *A = Args.getLastArg(options::OPT_target_profile)) {
StringRef Profile = A->getValue();
std::string Triple = tryParseProfile(Profile);
if (Triple == "") {
getDriver().Diag(diag::err_drv_invalid_directx_shader_module) << Profile;
Triple = ToolChain::ComputeEffectiveClangTriple(Args, InputType);
}
A->claim();
return Triple;
} else {
return ToolChain::ComputeEffectiveClangTriple(Args, InputType);
}
}
34 changes: 34 additions & 0 deletions clang/lib/Driver/ToolChains/HLSL.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//===--- HLSL.h - HLSL ToolChain Implementations ----------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#pragma once

#include "clang/Driver/ToolChain.h"

namespace clang {
namespace driver {

namespace toolchains {

class LLVM_LIBRARY_VISIBILITY HLSLToolChain : public ToolChain {
public:
HLSLToolChain(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
bool isPICDefault() const override { return false; }
bool isPIEDefault(const llvm::opt::ArgList &Args) const override {
return false;
}
bool isPICDefaultForced() const override { return false; }

std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
types::ID InputType) const override;
};

} // end namespace toolchains
} // end namespace driver
} // end namespace clang
1 change: 1 addition & 0 deletions clang/lib/Driver/Types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ types::ID types::lookupTypeForExtension(llvm::StringRef Ext) {
.Case("c++m", TY_CXXModule)
.Case("cppm", TY_CXXModule)
.Case("cxxm", TY_CXXModule)
.Case("hlsl", TY_HLSL)
.Default(TY_INVALID);
}

Expand Down
35 changes: 35 additions & 0 deletions clang/test/Driver/dxil_target_profile.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// RUN: %clang_dxc -Tvs_6_0 -Fo - %s 2>&1 | FileCheck %s --check-prefix=VS60
// VS60:target triple = "dxil-unknown-shadermodel6.0-vertex"

// RUN: %clang_dxc -Ths_6_1 -Fo - %s 2>&1 | FileCheck %s --check-prefix=HS61
// HS61:target triple = "dxil-unknown-shadermodel6.1-hull"

// RUN: %clang_dxc -Tds_6_2 -Fo - %s 2>&1 | FileCheck %s --check-prefix=DS62
// DS62:target triple = "dxil-unknown-shadermodel6.2-domain"

// RUN: %clang_dxc -Tgs_6_3 -Fo - %s 2>&1 | FileCheck %s --check-prefix=GS63
// GS63:target triple = "dxil-unknown-shadermodel6.3-geometry"

// RUN: %clang_dxc -Tps_6_4 -Fo - %s 2>&1 | FileCheck %s --check-prefix=PS64
// PS64:target triple = "dxil-unknown-shadermodel6.4-pixel"

// RUN: %clang_dxc -Tms_6_5 -Fo - %s 2>&1 | FileCheck %s --check-prefix=MS65
// MS65:target triple = "dxil-unknown-shadermodel6.5-mesh"

// RUN: %clang_dxc -Tas_6_6 -Fo - %s 2>&1 | FileCheck %s --check-prefix=AS66
// AS66:target triple = "dxil-unknown-shadermodel6.6-amplification"

// RUN: %clang_dxc -Tlib_6_x -Fo - %s 2>&1 | FileCheck %s --check-prefix=LIB6x
// LIB6x:target triple = "dxil-unknown-shadermodel6.15-library"

// RUN: %clang_dxc -### -Tps_3_1 -Fo - %s 2>&1 | FileCheck %s --check-prefix=INVALID
// INVALID:invalid profile : ps_3_1

// RUN: %clang_dxc -### -Tlib_6_1 -Fo - %s 2>&1 | FileCheck %s --check-prefix=INVALID2
// INVALID2:invalid profile : lib_6_1

// RUN: %clang_dxc -### -Tms_6_1 -Fo - %s 2>&1 | FileCheck %s --check-prefix=INVALID3
// INVALID3:invalid profile : ms_6_1

// RUN: %clang_dxc -### -Tas_6_4 -Fo - %s 2>&1 | FileCheck %s --check-prefix=INVALID4
// INVALID4:invalid profile : as_6_4
2 changes: 2 additions & 0 deletions clang/test/lit.cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@
'clang-tblgen', 'clang-scan-deps', 'opt', 'llvm-ifs', 'yaml2obj',
ToolSubst('%clang_extdef_map', command=FindTool(
'clang-extdef-mapping'), unresolved='ignore'),
ToolSubst('%clang_dxc', command=config.clang,
extra_args=['--driver-mode=dxc']),
]

if config.clang_examples:
Expand Down
Loading