Skip to content

Commit

Permalink
Add --PIC flag
Browse files Browse the repository at this point in the history
  • Loading branch information
nurmukhametov committed May 15, 2024
1 parent c2d80a6 commit 0f2b9fa
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 36 deletions.
3 changes: 2 additions & 1 deletion ispc-opt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ int main(int argc, char **argv) {
ispc::ISPCTarget target = ispc::ParseISPCTarget(TargetTarget);

// TODO: here, we rely on arch and cpu autodetection in ispc::Target constructor.
ispc::g->target = new ispc::Target(ispc::Arch::none, nullptr, target, false, ispc::MCModel::Default, false);
ispc::g->target =
new ispc::Target(ispc::Arch::none, nullptr, target, ispc::PICLevel::NotPIC, ispc::MCModel::Default, false);
if (!ispc::g->target->isValid()) {
ispc::Error(ispc::SourcePos(), "Unsupported target\n");
return 1;
Expand Down
17 changes: 9 additions & 8 deletions src/ispc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -674,15 +674,16 @@ class AllCPUs {
}
};

Target::Target(Arch arch, const char *cpu, ISPCTarget ispc_target, bool pic, MCModel code_model, bool printTarget)
Target::Target(Arch arch, const char *cpu, ISPCTarget ispc_target, PICLevel picLevel, MCModel code_model,
bool printTarget)
: m_target(nullptr), m_targetMachine(nullptr), m_dataLayout(nullptr), m_valid(false), m_ispc_target(ispc_target),
m_isa(SSE2), m_arch(Arch::none), m_is32Bit(true), m_cpu(""), m_attributes(""), m_tf_attributes(nullptr),
m_nativeVectorWidth(-1), m_nativeVectorAlignment(-1), m_dataTypeWidth(-1), m_vectorWidth(-1), m_generatePIC(pic),
m_codeModel(code_model), m_maskingIsFree(false), m_maskBitCount(-1), m_hasDotProductVNNI(false),
m_hasHalfConverts(false), m_hasHalfFullSupport(false), m_hasRand(false), m_hasGather(false), m_hasScatter(false),
m_hasTranscendentals(false), m_hasTrigonometry(false), m_hasRsqrtd(false), m_hasRcpd(false),
m_hasVecPrefetch(false), m_hasSaturatingArithmetic(false), m_hasFp16Support(false), m_hasFp64Support(true),
m_warnings(0) {
m_nativeVectorWidth(-1), m_nativeVectorAlignment(-1), m_dataTypeWidth(-1), m_vectorWidth(-1),
m_picLevel(picLevel), m_codeModel(code_model), m_maskingIsFree(false), m_maskBitCount(-1),
m_hasDotProductVNNI(false), m_hasHalfConverts(false), m_hasHalfFullSupport(false), m_hasRand(false),
m_hasGather(false), m_hasScatter(false), m_hasTranscendentals(false), m_hasTrigonometry(false),
m_hasRsqrtd(false), m_hasRcpd(false), m_hasVecPrefetch(false), m_hasSaturatingArithmetic(false),
m_hasFp16Support(false), m_hasFp64Support(true), m_warnings(0) {
DeviceType CPUID = CPU_None, CPUfromISA = CPU_None;
AllCPUs a;
std::string featuresString;
Expand Down Expand Up @@ -1693,7 +1694,7 @@ Target::Target(Arch arch, const char *cpu, ISPCTarget ispc_target, bool pic, MCM
llvm::Optional<llvm::CodeModel::Model> mcModel;
#endif

if (m_generatePIC) {
if (m_picLevel == PICLevel::SmallPIC || m_picLevel == PICLevel::BigPIC) {
relocModel = llvm::Reloc::PIC_;
}
switch (m_codeModel) {
Expand Down
14 changes: 11 additions & 3 deletions src/ispc.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,14 @@ enum class MCModel {
Large, /** large model */
};

/** PIC level. It corresponds to llvm::PICLevel. */
enum class PICLevel {
Default, /** default model - i.e. not specified on the command line */
NotPIC, /** not PIC */
SmallPIC, /** small PIC */
BigPIC, /** big PIC */
};

/** @brief Structure that defines a compilation target
This structure defines a compilation target for the ispc compiler.
Expand Down Expand Up @@ -220,7 +228,7 @@ class Target {
/** Initializes the given Target pointer for a target of the given
name, if the name is a known target. Returns true if the
target was initialized and false if the name is unknown. */
Target(Arch arch, const char *cpu, ISPCTarget isa, bool pic, MCModel code_model, bool printTarget);
Target(Arch arch, const char *cpu, ISPCTarget isa, PICLevel picLevel, MCModel code_model, bool printTarget);

~Target();

Expand Down Expand Up @@ -320,7 +328,7 @@ class Target {

int getVectorWidth() const { return m_vectorWidth; }

bool getGeneratePIC() const { return m_generatePIC; }
PICLevel getPICLevel() const { return m_picLevel; }

MCModel getMCModel() const { return m_codeModel; }

Expand Down Expand Up @@ -425,7 +433,7 @@ class Target {
int m_vectorWidth;

/** Indicates whether position independent code should be generated. */
bool m_generatePIC;
PICLevel m_picLevel;

/** Code model */
MCModel m_codeModel;
Expand Down
14 changes: 9 additions & 5 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2010-2023, Intel Corporation
Copyright (c) 2010-2024, Intel Corporation
SPDX-License-Identifier: BSD-3-Clause
*/
Expand Down Expand Up @@ -143,6 +143,8 @@ static void lPrintVersion() {
printf(" force-aligned-memory\t\tAlways issue \"aligned\" vector load and store instructions\n");
printf(" reset-ftz-daz\t\t\tReset FTZ/DAZ flags on ISPC extern function entrance / restore on return\n");
printf(" [--pic]\t\t\t\tGenerate position-independent code. Ignored for Windows target\n");
printf(" [--PIC]\t\t\t\tGenerate position-independent code avoiding any limit on the size of the global offset "
"table. Ignored for Windows target\n");
printf(" [--quiet]\t\t\t\tSuppress all output\n");
printf(" [--support-matrix]\t\t\tPrint full matrix of supported targets, architectures and OSes\n");
printf(" ");
Expand Down Expand Up @@ -1004,7 +1006,9 @@ int main(int Argc, char *Argv[]) {
value);
}
} else if (!strcmp(argv[i], "--pic"))
flags.setPIC(true);
flags.setPICLevel(PICLevel::SmallPIC);
else if (!strcmp(argv[i], "--PIC"))
flags.setPICLevel(PICLevel::BigPIC);
#ifndef ISPC_IS_HOST_WINDOWS
else if (!strcmp(argv[i], "--colored-output"))
g->forceColoredOutput = true;
Expand Down Expand Up @@ -1113,7 +1117,7 @@ int main(int Argc, char *Argv[]) {

// Default settings for PS4
if (g->target_os == TargetOS::ps4 || g->target_os == TargetOS::ps5) {
flags.setPIC();
flags.setPICLevel(PICLevel::BigPIC);
if (!cpu) {
if (g->target_os == TargetOS::ps4) {
// Default for PS4 is btver2, but do not enforce it.
Expand All @@ -1131,7 +1135,7 @@ int main(int Argc, char *Argv[]) {

// Default setting for "custom_linux"
if (g->target_os == TargetOS::custom_linux) {
flags.setPIC();
flags.setPICLevel();
if (!cpu) {
cpu = "cortex-a57";
}
Expand Down Expand Up @@ -1215,7 +1219,7 @@ int main(int Argc, char *Argv[]) {
}

if (g->target_os == TargetOS::windows && flags.isPIC()) {
Warning(SourcePos(), "--pic switch for Windows target will be ignored.");
Warning(SourcePos(), "--pic|--PIC switches for Windows target will be ignored.");
}

if (g->target_os != TargetOS::windows && g->dllExport) {
Expand Down
30 changes: 23 additions & 7 deletions src/module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,24 @@ static void lSetCodeModel(llvm::Module *module) {
used by some targets to generate code in the different way. Unlike code
model, it is not passed to the TargetMachine, so it is the only place for
codegen to access the correct value. */
static void lSetPicLevel(llvm::Module *module) {
module->setPICLevel(g->target->getGeneratePIC() ? llvm::PICLevel::SmallPIC : llvm::PICLevel::NotPIC);
static void lSetPICLevel(llvm::Module *module) {
PICLevel picLevel = g->target->getPICLevel();
switch (picLevel) {
case ispc::PICLevel::Default:
// We're leaving the default. There's a similar case in the LLVM
// frontend code where they don't set the level when pic flag is
// omitted in the command line.
break;
case ispc::PICLevel::NotPIC:
module->setPICLevel(llvm::PICLevel::NotPIC);
break;
case ispc::PICLevel::SmallPIC:
module->setPICLevel(llvm::PICLevel::SmallPIC);
break;
case ispc::PICLevel::BigPIC:
module->setPICLevel(llvm::PICLevel::BigPIC);
break;
}
}

///////////////////////////////////////////////////////////////////////////
Expand All @@ -239,7 +255,7 @@ Module::Module(const char *fn) : filename(fn) {
// DataLayout information supposed to be managed in single place in Target class.
module->setDataLayout(g->target->getDataLayout()->getStringRepresentation());
lSetCodeModel(module);
module->setPICLevel(g->target->getGeneratePIC() ? llvm::PICLevel::SmallPIC : llvm::PICLevel::NotPIC);
lSetPICLevel(module);

// Version strings.
// Have ISPC details and LLVM details as two separate strings attached to !llvm.ident.
Expand Down Expand Up @@ -3319,7 +3335,7 @@ static llvm::Module *lInitDispatchModule() {
AddBitcodeToModule(dispatch, module);

lSetCodeModel(module);
module->setPICLevel(g->target->getGeneratePIC() ? llvm::PICLevel::SmallPIC : llvm::PICLevel::NotPIC);
lSetPICLevel(module);

return module;
}
Expand Down Expand Up @@ -3444,7 +3460,7 @@ int Module::CompileAndOutput(const char *srcFile, Arch arch, const char *cpu, st
if (targets.size() == 1) {
target = targets[0];
}
g->target = new Target(arch, cpu, target, outputFlags.isPIC(), outputFlags.getMCModel(), g->printTarget);
g->target = new Target(arch, cpu, target, outputFlags.getPICLevel(), outputFlags.getMCModel(), g->printTarget);
if (!g->target->isValid())
return 1;

Expand Down Expand Up @@ -3571,7 +3587,7 @@ int Module::CompileAndOutput(const char *srcFile, Arch arch, const char *cpu, st
std::vector<Module *> modules(targets.size());
for (unsigned int i = 0; i < targets.size(); ++i) {
g->target =
new Target(arch, cpu, targets[i], outputFlags.isPIC(), outputFlags.getMCModel(), g->printTarget);
new Target(arch, cpu, targets[i], outputFlags.getPICLevel(), outputFlags.getMCModel(), g->printTarget);
if (!g->target->isValid())
return 1;

Expand Down Expand Up @@ -3666,7 +3682,7 @@ int Module::CompileAndOutput(const char *srcFile, Arch arch, const char *cpu, st
Assert(strcmp(firstISA, "") != 0);
Assert(firstTarget != ISPCTarget::none);

g->target = new Target(arch, cpu, firstTarget, outputFlags.isPIC(), outputFlags.getMCModel(), false);
g->target = new Target(arch, cpu, firstTarget, outputFlags.getPICLevel(), outputFlags.getMCModel(), false);
llvm::TargetMachine *firstTargetMachine = g->target->GetTargetMachine();
Assert(firstTargetMachine);
if (!g->target->isValid()) {
Expand Down
16 changes: 9 additions & 7 deletions src/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,22 +135,24 @@ class Module {
class OutputFlags {
public:
OutputFlags()
: pic(false), flatDeps(false), makeRuleDeps(false), depsToStdout(false), mcModel(MCModel::Default) {}
: picLevel(PICLevel::Default), flatDeps(false), makeRuleDeps(false), depsToStdout(false),
mcModel(MCModel::Default) {}
OutputFlags(OutputFlags &o)
: pic(o.pic), flatDeps(o.flatDeps), makeRuleDeps(o.makeRuleDeps), depsToStdout(o.depsToStdout),
: picLevel(o.picLevel), flatDeps(o.flatDeps), makeRuleDeps(o.makeRuleDeps), depsToStdout(o.depsToStdout),
mcModel(o.mcModel) {}

OutputFlags &operator=(const OutputFlags &o) {
pic = o.pic;
picLevel = o.picLevel;
flatDeps = o.flatDeps;
makeRuleDeps = o.makeRuleDeps;
depsToStdout = o.depsToStdout;
mcModel = o.mcModel;
return *this;
};

void setPIC(bool v = true) { pic = v; }
bool isPIC() const { return pic; }
void setPICLevel(PICLevel v = PICLevel::Default) { picLevel = v; }
PICLevel getPICLevel() const { return picLevel; }
bool isPIC() const { return picLevel != PICLevel::Default; }
void setFlatDeps(bool v = true) { flatDeps = v; }
bool isFlatDeps() const { return flatDeps; }
void setMakeRuleDeps(bool v = true) { makeRuleDeps = v; }
Expand All @@ -161,8 +163,8 @@ class Module {
MCModel getMCModel() const { return mcModel; }

private:
// --pic
bool pic;
// --pic --PIC
PICLevel picLevel;
// -MMM
bool flatDeps;
// -M
Expand Down
4 changes: 3 additions & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright (c) 2018-2023, Intel Corporation
# Copyright (c) 2018-2024, Intel Corporation
#
# SPDX-License-Identifier: BSD-3-Clause

Expand All @@ -25,6 +25,8 @@ list(APPEND LIT_ARGS "-Dwasm_enabled=$<IF:$<BOOL:${WASM_ENABLED}>,ON,OFF>")
list(APPEND LIT_ARGS "-Dxe_enabled=$<IF:$<BOOL:${XE_ENABLED}>,ON,OFF>")
# ISPC enabled OS.
list(APPEND LIT_ARGS "-Dwindows_enabled=$<IF:$<BOOL:${ISPC_WINDOWS_TARGET}>,ON,OFF>")
list(APPEND LIT_ARGS "-Dlinux_enabled=$<IF:$<BOOL:${ISPC_LINUX_TARGET}>,ON,OFF>")
list(APPEND LIT_ARGS "-Dps_enabled=$<IF:$<BOOL:${ISPC_PS_TARGET}>,ON,OFF>")
list(APPEND LIT_ARGS "-Dmacos_arm_enabled=$<IF:$<BOOL:${ISPC_MACOS_ARM_TARGET}>,ON,OFF>")
# ISPC opaque pointers
list(APPEND LIT_ARGS "-Dopaque_mode=$<IF:$<BOOL:${ISPC_OPAQUE_PTR_MODE}>,ON,OFF>")
Expand Down
20 changes: 20 additions & 0 deletions tests/lit-tests/lit.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,26 @@ elif windows_enabled == "OFF":
else:
sys.exit("Cannot parse windows_enabled: " + windows_enabled)

# Linux target OS is enabled
linux_enabled = lit_config.params.get('linux_enabled')
if linux_enabled == "ON":
print("LINUX_ENABLED: YES")
config.available_features.add("LINUX_ENABLED")
elif linux_enabled == "OFF":
print("LINUX_ENABLED: NO")
else:
sys.exit("Cannot parse linux_enabled: " + linux_enabled)

# PS target OSes are enabled
ps_enabled = lit_config.params.get('ps_enabled')
if ps_enabled == "ON":
print("PS_ENABLED: YES")
config.available_features.add("PS_ENABLED")
elif ps_enabled == "OFF":
print("PS_ENABLED: NO")
else:
sys.exit("Cannot parse ps_enabled: " + ps_enabled)

# ARM support on macOS target is enabled
macos_arm_enabled = lit_config.params.get('macos_arm_enabled')
if macos_arm_enabled == "ON":
Expand Down
18 changes: 18 additions & 0 deletions tests/lit-tests/pic-level-1.ispc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// RUN: %{ispc} --target=host --nostdlib --nowrap %s -o - --emit-llvm-text 2>&1 | FileCheck %s
// RUN: %{ispc} --target=host --nostdlib --nowrap %s -o - --emit-llvm-text --mcmodel=small 2>&1 | FileCheck %s
// RUN: %{ispc} --target=host --nostdlib --nowrap %s -o - --emit-llvm-text --mcmodel=large 2>&1 | FileCheck %s

// XFAIL: *

// TODO:
// There is a strange behavior in the current PIC handling. When --pic
// omitted LLVM IR contains "PIC Level", i32 2 but TargetMachine object is not
// initialized with relocModel = PIC_. It looks wrong and should be fixed but
// preserve this behavior for now.
// This especially strange considering that --mcmodel=large|small affects the
// PIC Level when --pic is omitted.

// CHECK: !"PIC Level", i32 0
uniform int global_var = 42;

uniform int foo() { return global_var; }
8 changes: 4 additions & 4 deletions tests/lit-tests/pic-level.ispc
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// RUN: %{ispc} --target=host --nostdlib --nowrap %s -o - --emit-llvm-text 2>&1 | FileCheck %s --check-prefix=CHECK-NOPIC
// RUN: %{ispc} --target=host --nostdlib --nowrap %s -o - --emit-llvm-text --pic 2>&1 | FileCheck %s --check-prefix=CHECK-PIC
// RUN: %{ispc} --target=host --nostdlib --nowrap %s -o - --emit-llvm-text --PIC 2>&1 | FileCheck %s --check-prefix=CHECK-BIGPIC
// RUN: %{ispc} --target=host --target-os=linux --nostdlib --nowrap %s -o - --emit-llvm-text 2>&1 | FileCheck %s --check-prefix=CHECK-NOPIC
// RUN: %{ispc} --target=host --target-os=linux --nostdlib --nowrap %s -o - --emit-llvm-text --pic 2>&1 | FileCheck %s --check-prefix=CHECK-PIC
// RUN: %{ispc} --target=host --target-os=linux --nostdlib --nowrap %s -o - --emit-llvm-text --PIC 2>&1 | FileCheck %s --check-prefix=CHECK-BIGPIC

// Note: in LLVM 16 the merge behaviour of PIC flags for Modules changed.
// Before, the merge value was the maximal. We are merging the flags from the
// user module, the builtin-cpp module and the target module. So, the PIC level
// of the resulted code depends not only on the user flags, but also on the
// flags that we build builtin and target modules.
// REQUIRES: LLVM_16_0+
// REQUIRES: LLVM_16_0+ && LINUX_ENABLED


// TODO: see tests/lit-tests/pic-level-1.ispc for more details.
Expand Down
11 changes: 11 additions & 0 deletions tests/lit-tests/ps-pic-level.ispc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// RUN: %{ispc} --target-os=ps4 --nostdlib --nowrap %s -o - --emit-llvm-text 2>&1 | FileCheck %s --check-prefix=CHECK-IR-PIC
// RUN: %{ispc} --target-os=ps4 --nostdlib --nowrap %s -o - --emit-llvm-text --pic 2>&1 | FileCheck %s --check-prefix=CHECK-IR-PIC
// RUN: %{ispc} --target-os=ps4 --nostdlib --nowrap %s -o - --emit-llvm-text --PIC 2>&1 | FileCheck %s --check-prefix=CHECK-IR-PIC

// REQUIRES: PS_ENABLED

// CHECK-IR-PIC: !"PIC Level", i32 2

uniform int global_var;

uniform int foo() { return global_var; }

0 comments on commit 0f2b9fa

Please sign in to comment.