Disallow native output with generic targets, C++ output with non-generic targets.
Also wrote FAQs about why this is the way it is. Issue #334.
This commit is contained in:
54
docs/faq.rst
54
docs/faq.rst
@@ -14,6 +14,11 @@ distribution.
|
|||||||
+ `Why are there multiple versions of exported ispc functions in the assembly output?`_
|
+ `Why are there multiple versions of exported ispc functions in the assembly output?`_
|
||||||
+ `How can I more easily see gathers and scatters in generated assembly?`_
|
+ `How can I more easily see gathers and scatters in generated assembly?`_
|
||||||
|
|
||||||
|
* Running The Compiler
|
||||||
|
|
||||||
|
+ `Why is it required to use one of the "generic" targets with C++ output?`_
|
||||||
|
+ `Why won't the compiler generate an object file or assembly output with the "generic" targets?`_
|
||||||
|
|
||||||
* Language Details
|
* Language Details
|
||||||
|
|
||||||
+ `What is the difference between "int *foo" and "int foo[]"?`_
|
+ `What is the difference between "int *foo" and "int foo[]"?`_
|
||||||
@@ -222,6 +227,55 @@ easier to understand:
|
|||||||
jmp ___pseudo_scatter_base_offsets32_32 ## TAILCALL
|
jmp ___pseudo_scatter_base_offsets32_32 ## TAILCALL
|
||||||
|
|
||||||
|
|
||||||
|
Running The Compiler
|
||||||
|
====================
|
||||||
|
|
||||||
|
Why is it required to use one of the "generic" targets with C++ output?
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
The C++ output option transforms the provided ``ispc`` program source into
|
||||||
|
C++ code where each basic operation in the program (addition, comparison,
|
||||||
|
etc.) is represented as a function call to an as-yet-undefined function,
|
||||||
|
chaining the results of these calls together to perform the required
|
||||||
|
computations. It is then expected that the user will provide the
|
||||||
|
implementation of these functions via a header file with ``inline``
|
||||||
|
functions defined for each of these functions and then use a C++ compiler
|
||||||
|
to generate a final object file. (Examples of these headers include
|
||||||
|
``examples/intrinsics/sse4.h`` and ``examples/intrinsics/knc.h`` in the
|
||||||
|
``ispc`` distribution.)
|
||||||
|
|
||||||
|
If a target other than one of the "generic" ones is used with C++ output,
|
||||||
|
then the compiler will transform certain operations into particular code
|
||||||
|
sequences that may not be desired for the actual final target; for example,
|
||||||
|
SSE targets that don't have hardware "gather" instructions will transform a
|
||||||
|
gather into a sequence of scalar load instructions. When this in turn is
|
||||||
|
transformed to C++ code, the fact that the loads were originally a gather
|
||||||
|
is lost, and the header file of function definitions wouldn't have a chance
|
||||||
|
to map the "gather" to a target-specific operation, as the ``knc.h`` header
|
||||||
|
does, for example. Thus, the "generic" targets exist to provide basic
|
||||||
|
targets of various vector widths, without imposing any limitations on the
|
||||||
|
final target's capabilities.
|
||||||
|
|
||||||
|
Why won't the compiler generate an object file or assembly output with the "generic" targets?
|
||||||
|
---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
As described in the above FAQ entry, when compiling to the "generic"
|
||||||
|
targets, ``ispc`` generates vector code for the source program that
|
||||||
|
transforms every basic operation in the program (addition, comparison,
|
||||||
|
etc.) into a separate function call.
|
||||||
|
|
||||||
|
While there is no fundamental reason that the compiler couldn't generate
|
||||||
|
target-specific object code with a function call to an undefined function
|
||||||
|
for each primitive operation, doing so wouldn't actually be useful in
|
||||||
|
practice--providing definitions of these functions in a separate object
|
||||||
|
file and actually performing function calls for each of them (versus
|
||||||
|
turning them into inline function calls) would be a highly inefficient way
|
||||||
|
to run the program.
|
||||||
|
|
||||||
|
Therefore, in the interests of encouraging the use of the system,
|
||||||
|
these types of output are disallowed.
|
||||||
|
|
||||||
|
|
||||||
Language Details
|
Language Details
|
||||||
================
|
================
|
||||||
|
|
||||||
|
|||||||
16
module.cpp
16
module.cpp
@@ -2168,6 +2168,22 @@ Module::CompileAndOutput(const char *srcFile,
|
|||||||
|
|
||||||
m = new Module(srcFile);
|
m = new Module(srcFile);
|
||||||
if (m->CompileFile() == 0) {
|
if (m->CompileFile() == 0) {
|
||||||
|
if (outputType == CXX) {
|
||||||
|
if (target == NULL || strncmp(target, "generic-", 8) != 0) {
|
||||||
|
Error(SourcePos(), "When generating C++ output, one of the \"generic-*\" "
|
||||||
|
"targets must be used.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (outputType == Asm || outputType == Object) {
|
||||||
|
if (target != NULL && strncmp(target, "generic-", 8) == 0) {
|
||||||
|
Error(SourcePos(), "When using a \"generic-*\" compilation target, "
|
||||||
|
"%s output can not be used.",
|
||||||
|
(outputType == Asm) ? "assembly" : "object file");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (outFileName != NULL)
|
if (outFileName != NULL)
|
||||||
if (!m->writeOutput(outputType, outFileName, includeFileName))
|
if (!m->writeOutput(outputType, outFileName, includeFileName))
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user