Age | Commit message (Collapse) | Author | Files | Lines |
|
Currently, OP_PHISOURCES have a list as member, 'phi_users',
that should link to all phi-nodes using them but:
*) phi-sources are never shared between phi-nodes
*) this list is useless because it's only created during liveness
and not used after.
So, replace the list by a simple pointer to hold the unique phi-node
using it and keep this link updated during all its lifetime.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
|
|
Convert OP_SETVAL of a label into a new instruction: OP_LABEL.
There is 2 reasons to do this:
*) there is slightly less checking to be done in later phases
(since OP_SETVAL can be for labels but also strings)
*) OP_SETVAL is CSEd but this is largely useless because this
instruction is hashed on the expression's address and these
are (most) often not shared. With a separate instruction
for label expressions, their CSE is now OK because the hashing
is done on the BB.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
sparse-llvm crashes with LLVM-11. From what I can see, it's because
LLVM-11 doesn't like anymore that an instruction is first created
unattached to a basic block (LLVMClearInsertionPosition()) and
inserted at some later step (LLVMInsertIntoBuilder()). Since the
corresponding function still exist I suppose they're working correctly
and sparse-llvm somehow misuse them. I don't know.
However, this functionality is only used to create the alloca
instructions used to simulate the phi-nodes.
So, fix this crash by using real phi instructions for the phi-nodes.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
* do 'classical' SSA conversion (via the iterated dominance frontier).
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Processing in the middle-end are much easier if undefined values
have been clearly identified. Once done, we can then make
choices like:
- give some warnings about uninitialized variables
- always initialize them to zero
- allow arbitraly simplification
- ...
Prepare this by declaring a new type of pseudo: PSEUDO_UNDEF
somewhat similar to PSEUDO_VOID.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
* optimize away OP_UTPTR & OP_PTRTU which are nops.
|
|
Now that all casts to or from a pointer are between a pointer
and a pointer-sized unsigned integer, from an optimization
PoV, they are all no-ops.
So, optimize them away at simplification time.
Note: casts between pointers (OP_PTRCAST) should also be
optimized away but the original type is used for a
number a things (for example in check_access()) and
can't be optimized away so simply (yet).
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Now that these instructions are not generated anymore,
we can remove all related code, defines and doc.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Casts to integer used to be done with only 2 instructions:
OP_CAST & OP_SCAST.
Those are not very convenient as they don't reflect the real
operations that need to be done.
This patch specialize these instructions in:
- OP_TRUNC, for casts to a smaller type
- OP_ZEXT, for casts that need a zero extension
- OP_SEXT, for casts that need a sign extension
- Integer-to-integer casts of the same size are considered as
a NOPs and are, in fact, never emitted.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Currently all casts to pointers are processed alike. This is
simple but rather unconvenient in later phases as this
correspond to different operations that obeys to different
rules and which later need extra checks.
Change this by using a specific instructions (OP_UTPTR) for
[unsigned] integer to pointers.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Currently all casts to pointers are processed alike.
This is simple but rather unconvenient as it correspond to
different operations that obeys to different rules and
which later need extra checks.
Change this by using a specific instructions (OP_UTPTR) for
unsigned integer to pointers.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Currently, casts from floats to integers are processed like
integers (or any other type) to integers. This is simple but
rather unconvenient as it correspond to different operations
that obeys to different rules and which later need extra checks.
Change this by directly using specific instructions:
- FCVTU for floats to unsigned integers
- FCVTS for floats to signed integers
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Currently, all casts to a floating point type use OP_FPCAST.
This is maybe simple but rather uncovenient as it correspond
to several quite different operations that later need extra
checks.
Change this by directly using different instructions for the
different cases:
- FCVTF for float-float conversions
- UCVTF for unsigned integer to floats
- SCVTF for signed integer to floats
and reject attempts to cast a pointer to a float.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Now that FOR_EACH_PTR() doesn't strip the tag anymore, there
is no more needs for FOR_EACH_PTR_NOTAG() as both do the same.
So convert the few uses to FOR_EACH_PTR() and remove its definition.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Non-null pointers were discarded and a NULL pointer was used instead.
Fix this by adding the missing 'else'.
Fixes: 18434703507423b58ecefe941438755525ec834a
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
In struct instruction, .target is normally used to hold
the result. Its value is thus produced/defined by instructions.
On the contrary, .cond is used as an input value and is
thus used by instructions.
However, these two fields belong to the same union. This
creates slight complications for code, like liveness analysis
which care about which fields are used and which are defined
by the instructions.
Change this by unionizing .cond with .src, .src1 & friends instead
of with .target.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
No instructions have an opcode set to OP_[LS]NOP anymore
so we can now remove all remaining traces of these opcode.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Currently, we have OP_MULS & OP_MULU but unless it's full,
widening multiplication both must give exactly the same
result (the world run on 2's complement CPUs now, right?).
Also, the IR doesn't have widening multiplication but
only instruction where both operands and the result have
the same size.
So, since theer is no reasons to keep 2 instructions,
merge OP_MULS & OP_MULU into a single one: OP_MUL.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
In sym_func_type(), a few variables are initialized
just after they are declared.
Change this to initialize them directly at their
declaration, which is simpler and more idiomatic.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The function sym_func_type() contains a small loop
which count the number of arguments, one by one.
Do this more simply and more efficiently by using
symbol_list_size().
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
OP_SETVAL is used to create floating-point and string
as well as labels-as-values. This multi-purpose aspect
sometimes make things a bit more complicated.
Change this by using a new instruction for the direct
creation of floating-point literals without needing
to have an intermediate EXPR_FVALUE.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
'testcase-fix-missing-return', 'type-as-first-class', 'llvm-zero-init' and 'llvm-prototype' into tip
|
|
Linearization of arrays & structs default initialization is done
as if these objects would be an integer as large as the object.
This integer is then simply zero-initialized.
(This may be objectionable and will be done differently).
However, sparse-llvm is not ready to handle this situation where
a non-scalar is initialized with a scalar value.
Workaround this by using LLVMConstNull() when possible.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Most pointers with a constant value are simply null-pointers.
The only exception is when a known address is casted to pointer.
The current code only handle code for the general case:
emit code for a constant integer and then cast this to a pointer.
This obfuscate a bit the ouput, making it hard to read.
Change this by special handling the normal case of null-pointers
by directly using LLVM's LLVMConstPointerNull().
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Currently, for the LLVM's IR, the functions are only declared
when they are called (or otherwise used) or when they are defined,
whichever come first. But systematically adding a declaration
for each function we have the prototype shouldn't hurt and
would add one level of type checking.
Change this by adding the declaration (via get_sym_value())
for each prototype we have.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
This function only need the reference for the module,
but currently is given the whole 'struct function'.
Change this by directly passing the module reference to
get_sym_value() so that this function can now be used
before the 'struct function' is created.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
In sparse-llvm, when a reference to a function is made via
get_sym_value(), for example for a call, the reference is
created with LLVMAddFunction() and if needed later, the existing
reference is returned via LLVMGetNamedFunction().
This is the correct way to do it.
However, when emitting the code for a function definition, a fresh
reference is always made. If a previous reference to this function
already existed, the second one will have a slightly different name:
the given name suffixed by ".<somenumber>". LLVM does this for every
created references, to disambiguate them. As consequence, the
compiled function will not be name "<functionname>", as expected,
but "<functionname>.<somenumber>".
Fix this by always using get_sym_value() when emitting the code
for the function definition as this will return the reference
for the given function name if it already exist.
This has the added bonus to remove some code duplication.
CC: Dibyendu Majumdar <mobile@majumdar.org.uk>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Floating-point arithmetic is quite different from the
arithmetic on integers or the one of real numbers.
In particular, most transformations, simplifications that can
be done on integers are invalid when done on floats.
For example:
- associativity doesn't hold
- distributivity doesn't hold
- comparison is tricky & complex
This is because (among others things):
- limited precision, rounding everywhere
- presence of signed zeroes
- presence of infinities
- presence of NaNs (signaling or quiet)
- presence of numbers without inverse
- several kind of exceptions.
Since they don't follow the same rules as their integer
counterpart, better to give them a specific opcode
instead of having to test the type of the operands at
each manipulation.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Comparision of floating-point values can't be done
like for integral values because of the possibility to have
NaNs which can't be ordered with normal values or even between
themselves.
The real difference appears once there is any "reasoning"
done with the result of the comparison. For example, once NaNs
are taken in account: "!(a < b)" and "(a >= b)" are not the same.
In fact the usual comparison operators must be reinterpreted
as implicitely first testing if any of the operand is a Nan
and return 'false' if it is the case. Thus "a < b" becomes
"!isnan(a) && !isnan(b) && (a < b)".
If we need to negate the comparison we get "!(a < b)" which
naturally becomes "isnan(a) || isnan(b) || (a >= b)".
We thus need two sets of operators for comparison of floats:
one for the "ordered" values (only true if neither operand
is a Nan) and one for the "values" (also true if either
operand is a NaN). A negation of the comparison switch from one
of the set to the other.
So, introduce another set of instructions for the comparison
of floats.
Note: the C standard requires that:
*) "x == x" is false if x is a NaN,
*) "x != x" is true if x is a NaN,
and this is coherent with "x != x" <-> "!(x == x)".
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
LLVM use a stricter type system for its IR than sparse does.
In the present case, sparse allow to compare pointers regardless
of their types.
This create LLVM errors if we try to simply translate, instruction
by instruction, sparse's compare instructions to LLVM ones.
Fix this by casting all pointers to void *, before comparing them.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Currently, sparse-llvm can't emit the needed code for
all initializers and when it's the case it stop abruptly
with an assert(0).
This is kinda useless.
Somehow fix this by issuing a warning instead and try to
continue gracefully.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Until now, in sparse-llvm, an assert(0) was used each time
something which was not yet handled was encountered.
This is doubly annoying because:
- the assert gave no info about the cause
- it also hide possible further issuses.
Fix this by:
- removing the asserts
- use a warnng explaining what's at hand
- try to continue with the following instructions.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
LLVM automatically add an numeric suffix for names
automatically created. So, if intermediate names must
be created for a pseudo whose name was, for example, "%R4",
these new names will be "%R41", "%R42".
This is quite annoying because we can't make the distinction
between these names and the original names, (maybe of some other
pseudos whose names were "%R41" & "%R42).
Change this by adding a "." at the end of each name, as this will
then allow to see what the original name was.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The linearized code, sparse's IR, have no use of C's complex type
system. Those types are checked in previous phases and the pseudos
doesn't have a type directly attached to them as all the needed
typing info info are conveyed by the instructions.
In particular, PSEUDO_VAL (used for integer and address constants)
are completely typeless.
There is a problem with this when calling a variadic function
with a constant argument as in this case there is no type in the
function prototype (for the variadic part, of course) and there is
no defining instructions holding the type of the argument.
Fiw this by using the type of the arguments explicitly given
in the OP_CALL instructions.
Reported-by: Dibyendu Majumdar <mobile@majumdar.org.uk>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
In sparse-llvm, the type of switch constants are hardcoded
to 'i32'.
Fix this by using the right type as given by the instruction.
Reported-by: Dibyendu Majumdar <mobile@majumdar.org.uk>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
It appears that when a function is compiled, its variadic flag is not
being set in LLVM so LLVM complains when at call sites variable
arguments are passed.
Reported-by: Dibyendu Majumdar <mobile@majumdar.org.uk>
Originally-by: Dibyendu Majumdar <mobile@majumdar.org.uk>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Pointer arithmetic and/or simplification can mixup pointer
and integer types.
Fix this by adding casts before all non-floating point binops
and adjust the result type if needed to match the instructio.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Since sparse's constant are typeless comparing a pointer with
an address constant lack correct type information.
Fix this by casting the constant to the same type as the LHS.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
In output_op_compare() everything that is not of interger
type is treated as floats. Pointers disagree.
Fix this by rearranging the code and treat pointers like integers
as required for LLVM's icmp.
Reported-by: Dibyendu Majumdar <mobile@majumdar.org.uk>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
sparse-llvm has not yet support for OP_NEG and stop on an assert
if one is encountered.
Fix this by invoking the appropriate LLVMBuild[F]Neg().
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
OP_PTRCASTs can't always be directly translated into LLVM bitcasts and
OP_[S]CASTs can't always be translated into LLVM's trunc/sext/zext
because integer to pointer and pointer to integer must be handled too.
Fix this in output_op_ptrcast() & output_op_cast() by issuing
LLVMBuildIntToPtr/PtrToInt when appropriate.
Reported-by: Dibyendu Majumdar <mobile@majumdar.org.uk>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
In sparse-llvm the field 'priv' of a pseudo is used to store
the corresponding LLVMValueRef. This field is normaly assigned
when processing the instruction that produces the speudo.
In output_op_store(), the field insn->target->priv is overwritten
by the LLVMValueRef returned by LLVMBuildStore().
It's unclear what this return value is:
- this corrupts the pseudo, making it unusable in subsequent
instructions.
- there is no reason to change this field anyway.
Fix this by removing the assignment to insn->target->priv
in output_op_store().
Reported-by: Dibyendu Majumdar <mobile@majumdar.org.uk>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
In sparse-llvm there is the assumption that a PSEUDO_VAL is always
of integer type. But this is not always the case: constant pointers,
like NULL, are also of the PSEUDO_VAL kind.
Fix this by adding a helper 'val_to_value()' and using the
instruction's type where this pseudo is used as the type of the value.
Note: while this patch improve the situation, like for example for the
test cases added here, it's still not correct because now we're making
the assumption that 'insn->type' is the type we need for the pseudo.
This is often true, but certainly not always.
For example this is not true for:
- OP_STORE/OP_LOAD's insn->src
- OP_SET{EQ,...}'s insn->src[12]
- probably some others ones
- in general, obviously, for any instructions where the target has
a different type than the operands.
Reported-by: Dibyendu Majumdar <mobile@majumdar.org.uk>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Currently, a name is given to the result of instruction like
binops, compares, ... but not to function calls.
Functionally, it doesn't change anything but those names are
useful by easing reading while debugging, reading the generated
code, ...
Fix this by giving a name to OP_CALL's result too.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Arguments, like all LLVMValues, are given a default name
but these name are simply '%0', '%1', ... and are thus not
very readable.
Fix this by giving them an explicit name 'ARG1', ... to
match the names used in sparse's linearized code.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
It's not needed here since there is no recursive access to BBs.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
OP_BR instructions exist in two flavours, relatively much
differentiated: conditional & non-conditional. One has an
operand (and thus its usage need to be cared for, must be
handled in liveness analysis, ..) the other has not; one has
two BB target, the other only one.
There is essentially no places in the code where both flavours
are handled the same. Sometimes they both must be handled but
each with their specificities but in most cases only one of
them is concerned and we need to filter out the other one.
In both cases it means that we need to check what kind we're
dealing with.
There is already a problem with this because there is
several ways to test which kind an OP_BR is and they
are not exactly equivalent:
1) testing if insn->cond is NULL
2) testing if one of insn->bb_true or ->bb_false is NULL.
There exist also an helper (is_branch_goto()) which does
the second tests but which is never used.
It appears that the first test should not be used because
in some cases an conditional OP_BR is changed into
a non-conditional one by (amongst others things) setting
it's ->cond to VOID. We should thus always use the seconds
test (which need two compares with NULL).
This could be corrected in several ways (like changing all
the places wheer the first test is used, use the helper
everywhere or never set ->cond to VOID) but the simplest
is to simply split them in two separated instructions:
OP_BR & OP_CBR, especailly given the fact that in most cases
the OP_BR was first selected by a switch (opcode).
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
OP_COPY instructions are only introduced by the 'unSSA' phase
which is not used by sparse-llvm.
Remove the code which tried to handle this.
Cc: Azat Khuzhin <a3at.mail@gmail.com>
Cc: Xi Wang <xi.wang@gmail.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
In translation to LLVM, comparisons are processed like usual binary
operations. But contrary to, for example, an addition where the
result type and the type of both operands are all the same, a
comparison always returns an integer result (with boolean values)
which shouldn't depends on the type/size of its operands.
There is currently a bug regarding this when an operand of a
comparison is an integer constant:
the type of this constant is assumed to be the type of the result
of the comparison (in sparse's IR, the constants are typeless,
we thus need to guess/retrieve their type from the context)
For example, with the following C code:
_Bool foo(int a) { return a != 3; }
After linearization we can have the following very straightforward:
setne.1 %rd <- %arg1, $3
And we expect the following LLVM IR:
%rd = icmp ne i32 %0, 3
But what is built is the illegal:
%rd = icmp ne i32 %0, i1 true
because is constant '3' is translated to 'i1 true' since
'setne.1' result type is boolean (i1 in LLVM parlance).
Fix this by separating the code for comparison from the others
binary operations and using the left-hand side type to interpret
the type of the constant (which is fine because the usual conversion
insure that both types match and there is never a constant on the lhs).
Cc: Azat Khuzhin <a3at.mail@gmail.com>
Cc: Xi Wang <xi.wang@gmail.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
You can't pass function to LLVMConstNull(), according to
Constant::getNullValue, and sparse-llvm already handle functions differently
(i.e. there will be no call to LLVMConstNull(), but this is not true for
function prototypes, because of how linearize_fn() works:
```
static struct entrypoint *linearize_fn(...)
{
...
if (!base_type->stmt)
return NULL;
...
}
```
```
Constant *Constant::getNullValue(Type *Ty) {
switch (Ty->getTypeID()) {
...
default:
// Function, Label, or Opaque type?
llvm_unreachable("Cannot create a null constant of that type!");
}
}
```
Signed-off-by: Azat Khuzhin <a3at.mail@gmail.com>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
The result type of relational operators (e.g., x < y) and logical
operators (e.g., x && y) in C should be int, rather than bool.
For example, sparse incorrectly evaluates sizeof(x < y) to 1 (i.e.,
sizeof(int)), which should have been sizeof(int).
This patch fixes the result type of these operators in evaluation,
linearization, and the LLVM backend.
Acked-by: Christopher Li <sparse@chrisli.org>
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Stop code generation if anything is wrong in front-end.
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Set const, thread_local, and alignment for global variables.
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Avoid null pointer dereference when ->ident is null (e.g., anonymous
struct). Also, use ->aux to avoid recursion.
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Cache symbol_type() result in ->aux to avoid recomputation.
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
The array size should be ->bit_size over that of its element type,
rather than ->bit_size / 8.
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Stick to LLVM_DEFAULT_TARGET_TRIPLE since LLVM_HOSTTRIPLE doesn't exist
on trunk anymore. Define LLVM_DEFAULT_TARGET_TRIPLE to LLVM_HOSTTRIPLE
for building with older LLVM.
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Switch to LLVM_HOSTTRIPLE to make sparse-llvm compile with LLVM 3.0.
Acked-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Set target triple and data layout, which are required by LLVM's backend.
Also export arch_m64 for choosing the target architecture.
Cc: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Converting pointers to integers for pointer arithmetic effectively
disables pointer analysis and future optimizations. A better way is to
use LLVM's GEP, by converting pointers to `char *' rather than integers.
Acked-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
LLVM needs to be correctly told about the type of the object
being accessed.
This patch also fixes code generation for struct accesses.
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Use the fix from d5bd3662 ("sparse, llvm: Fix type of loaded values").
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Remove repeated code, such as get_func_type() vs sym_func_type(),
pseudo_type() vs symbol_type().
Fix generating variadic functions.
Add a test case using printf().
Cc: Jeff Garzik <jgarzik@redhat.com>
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
PHI in LLVM is different from that in sparse. LLVM requires PHI "for
each predecessor basic block of the current block" even if the current
block doesn't use it. It's tricky to correctly place PHI.
This patch implements a simpler and safer strategy:
1) allocate an alloca for each phi, and
2) translate phi/phisrc to load/store alloca.
LLVM optimizations will promote load/store to registers.
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Instead of making the computed address a pointer to an int type
large enough to hold a pointer, make it a pointer to the memory
object being loaded. This fixes another LLVM warning.
Cc: Pekka Enberg <penberg@kernel.org>
Cc: Christopher Li <sparse@chrisli.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Acked-by: Jeff Garzik <jgarzik@redhat.com>
Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
LLVM expects the first argument of "br" and "select" to be of type i1,
so add an "icmp ne <srcty> %src, 0" for other types.
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Jonathan Neuschäfer reports:
A simple function like this will compile to the following llvm
bitcode:
/* C */
void func(void) {
return;
}
/* LLVM */
define i8 @func() {
L0:
ret void
}
The return type of the function and the type in the return instruction
don't match.
I found this inconsistency by running LLVM's bitcode validation on the
bitcode produced by sparse-llvm.
Move 'void *' special-casing from sym_basetype_type() to sym_ptr_type()
to fix the issue.
Reported by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
In later versions sparse-llvm should stop on wrong llvm code, instead
of outputting it, but for now there are too many warnings being produced
for this to be feasible (I think).
Cc: Pekka Enberg <penberg@kernel.org>
Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Jonathan Neuschäfer writes:
compiling a little real-world program with sparse-llvm, it segfaulted.
Using a tool called "delta"[1] and some bash scripting, I managed to
reduce the code to this test case:
extern struct foo *foop;
extern void func(struct foo *f);
int main(int argc, char **argv) {
func(foop);
}
The problem is that pseudo_to_value() does not know abou the extern
symbol because Sparse never calls output_data() on it which registers
globals with LLVMAddGlobal().
As explained by Linus, 'extern' symbols are just names with types. They
don't have any value associated with them, they just have the type and
the name. Therefore we need to explicitly call LLVMAddGlobal() for
symbols we have not encountered in pseudo_to_value().
Reported by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
This patch attempts to fix code generation for global string access:
static char *foo = "Foo !\n";
extern int puts(const char *s);
int main(int argc, char *argv[])
{
puts(foo);
return 0;
}
The generated executable causes a SIGSEGV:
[penberg@tux sparse]$ ./sparsec foo.c && ./a.out
Segmentation fault
But as pointed out by Xi Wang, the problem is in "output_load()":
I guess the problem is that sparse-llvm generates an incorrect type `load i64*'
in llvm from the sparse instruction load.64.
load.64 %r2 <- 0[foo]
call.32 %r1 <- puts, %r2
ret.32 $0
With the new ->ctype in pseudo sparse-llvm should be able to generate the
correct type. I am playing with an LLVM backend with typed pseudos; it
generates the following code, which seems okay.
@0 = internal global [7 x i8] c"Foo !\0A\00", align 1
@foo = internal global i8* getelementptr inbounds ([7 x i8]* @0, i64 0, i64 0), align 8
define i32 @main(i32 %argc, i8** %argv) {
entry:
%0 = load i8** @foo
%1 = call i32 @puts(i8* %0)
ret i32 0
}
So I'll leave the output_load() fix to a separate patch for now.
Cc: Xi Wang <xi.wang@gmail.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Christopher Li <sparse@chrisli.org>
Acked-by: Jeff Garzik <jgarzik@redhat.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
This fixes code generation for string initializer such as:
static char *foo = "Foo !\n";
It's the same fix Ben proposed earlier with the small difference that we now
use LLVMTypeOf() instead of symbol_type() to resolve the type.
The generated LLVM IR looks as follows:
[penberg@tux sparse]$ ./sparse-llvm foo.c |llvm-dis
; ModuleID = '<stdin>'
@"<noident>" = private global [7 x i8] c"Foo !\0A\00"
@foo = private global [7 x i8]* @"<noident>"
Reported-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Christopher Li <sparse@chrisli.org>
Acked-by: Jeff Garzik <jgarzik@redhat.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Use LLVMTypeOf() in output_data() to simplify type handling logic.
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Christopher Li <sparse@chrisli.org>
Acked-by: Jeff Garzik <jgarzik@redhat.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
We need to tell llvm about it or it won't generate the proper
stack frame & argument list on some architectures.
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
[ penberg@kernel.org: Fix function pointer calls ]
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
In preparation for reverting commit 2ded1e7 ("sparse: Bump up sizeof(_Bool) to
8 bits"), teach sym_basetype_type() about LLVMInt1Type().
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Previous code simply omitted PHI sources that had not been assigned a
LLVMValueRef at the time of OP_PHI.
Fix by creating a list of such instances, and attempt to resolve forward
references at each OP_PHISOURCE appearance.
Testcase:
extern int bar (int);
int foo (int x)
{
int y = 0;
while (y < 1000) {
y += bar(x);
}
return y;
}
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
|
|
This patch implements code generation for floating point versions of OP_BINCMP.
Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Linus writes:
On Tue, Nov 22, 2011 at 9:40 AM, Pekka Enberg <penberg@kernel.org> wrote:
> This patch implements LLVM code generation for OP_SET_LE, OP_SET_GE, OP_SET_BE,
> and OP_SET_AE.
Ugh.
Can't you just do it with a single statement like
target = LLVMBuildICmp(fn->builder, translate_op(op), lhs, rhs,
target_name);
instead of having that case-statement where every case does the same thing?
The translate_op() thing should be trivial too, just something like
static int translate_op(int sparse_op)
{
static const int trans_tbl[] = {
.[OP_SET_LE] = LLVMIntSLE,
...
};
return trans_tbl[sparse_op];
}
or whatever. No?
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
This patch implements LLVM code generation for OP_SET_LE, OP_SET_GE, OP_SET_BE,
and OP_SET_AE.
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
This patch implement unsigned less than and greater than comparison operator
LLVM code generation.
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
This patch implement code generation for OP_PTRCAST using LLVMBuildBitCast().
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
LLVMExternalLinkage is used for both extern and non-extern C symbols. The
linkage is differentiated by LLVMSetInitializer() which is should not be called
for extern symbols.
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
The output_data() function does not see right hand side symbols for expressions
such as this in target.c:
struct symbol *size_t_ctype = &uint_ctype;
Therefore, call output_data() recursively if LLVMGetNamedGlobal() returns NULL
for a symbol.
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
This patch implements support for function pointer types and function pointer
calls to the LLVM backend.
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
This patch adds support for SYM_UNION in symbol_type(). The LLVM API does not
provide support for unions so we treat them as opaque structs.
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
This patch adds support for SYM_ARRAY in symbol_type().
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
This patch adds SYM_BITFIELD and SYM_ENUM support to symbol_type().
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Use LLVMGetTypeByName() to look up struct data types to fix code generation for
structs that refer to themselves.
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
To fix an issue with structs that refer to themselves:
struct symbol {
struct symbol *next;
};
convert the code to use new type system API introduced in LLVM 3.0 so that
there's a LLVMTypeRef of the struct we can look up while walking through the
struct members.
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Sparse front-end generates SYM_PTR with SYM_BASETYPE with bit_size set to -1
for "void *" pointers. We currently map that to LLVMVoidType() but that no
longer works with LLVM Subversion trunk:
$ ./sparse-llvm validation/backend/struct.c
sparse-llvm: Type.cpp:676: static llvm::PointerType* llvm::PointerType::get(llvm::Type*, unsigned int): Assertion `isValidElementType(EltTy) && "Invalid type for pointer element!"' failed.
Aborted
Fix the issue by treating 'void *' as 'char *' as suggested by Linus:
On Mon, 24 Oct 2011, Linus Torvalds wrote:
> Why bits_per_pointer? Isn't this the "base type" of void *? A more
> logical choice would seem to be to make it equivalent to "char *", and
> just make it fall through to the "case 8" case?
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
The generated asm for logical-ops.c test case looks as follows on x86-64:
GCC 4.6:
0000000000000000 <and_bool>:
0: 31 c0 xor %eax,%eax
2: 85 f6 test %esi,%esi
4: 0f 95 c0 setne %al
7: 31 d2 xor %edx,%edx
9: 85 ff test %edi,%edi
b: 0f 95 c2 setne %dl
e: 21 d0 and %edx,%eax
10: c3 retq
0000000000000020 <uand_bool>:
20: 31 c0 xor %eax,%eax
22: 85 f6 test %esi,%esi
24: 0f 95 c0 setne %al
27: 31 d2 xor %edx,%edx
29: 85 ff test %edi,%edi
2b: 0f 95 c2 setne %dl
2e: 21 d0 and %edx,%eax
30: c3 retq
0000000000000040 <or_bool>:
40: 09 fe or %edi,%esi
42: 0f 95 c0 setne %al
45: 0f b6 c0 movzbl %al,%eax
48: c3 retq
0000000000000050 <uor_bool>:
50: 09 fe or %edi,%esi
52: 0f 95 c0 setne %al
55: 0f b6 c0 movzbl %al,%eax
58: c3 retq
Sparse/LLVM:
0000000000000000 <and_bool>:
0: 85 f6 test %esi,%esi
2: 0f 95 c0 setne %al
5: 85 ff test %edi,%edi
7: 0f 95 c1 setne %cl
a: 20 c1 and %al,%cl
c: 0f b6 c1 movzbl %cl,%eax
f: c3 retq
0000000000000010 <uand_bool>:
10: 85 f6 test %esi,%esi
12: 0f 95 c0 setne %al
15: 85 ff test %edi,%edi
17: 0f 95 c1 setne %cl
1a: 20 c1 and %al,%cl
1c: 0f b6 c1 movzbl %cl,%eax
1f: c3 retq
0000000000000020 <or_bool>:
20: 09 f7 or %esi,%edi
22: 0f 95 c0 setne %al
25: 0f b6 c0 movzbl %al,%eax
28: c3 retq
0000000000000030 <uor_bool>:
30: 09 f7 or %esi,%edi
32: 0f 95 c0 setne %al
35: 0f b6 c0 movzbl %al,%eax
38: c3 retq
Cc: Christopher Li <sparse@chrisli.org>
Cc: Jeff Garzik <jgarzik@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
testcase:
int foo(int *addr_i, int x)
{
*addr_i = x;
return x;
}
|
|
|
|
Fixes testcase:
int sum(int x, int y)
{
return x + y;
}
int main(int argc, char *argv[])
{
return sum(1, 2);
}
|
|
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Conflicts:
sparse-llvm.c
|
|
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Use with PSEUDO_VAL.
Also, remove needless braces around PSEUDO_ARG.
|
|
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
This reverts commit be40b1a0e49a97f084c67d2ffc866b1445445d44.
Jeff Garzik explains:
That last commit isn't quite right. The code before wasn't quite right either,
but the new commit doesn't do a whole lot:
commit be40b1a0e49a97f084c67d2ffc866b1445445d44
Author: Pekka Enberg <penberg@kernel.org>
Date: Tue Aug 30 18:10:25 2011 +0300
sparse, llvm: Don't redefine module local functions
Signed-off-by: Pekka Enberg <penberg@kernel.org>
First problem: we already have a list of function calling conventions cached
for use. That is what llfunc_list is.
However... this is _very wrong_ for varargs functions. Your commit changes to
using an LLVM list from a local list, but that does not fix the problem.
This test case should demonstrate the broken code:
int foo(int x, int y)
{
printf("%d\n", x);
printf("%d, %d\n", x, y);
return 0;
}
The first printf() cached [incorrectly] the list of arguments. c.f. this code
comment:
/* to avoid strangeness with varargs [for now], we build
* the function and type anew, for each call. This
* is probably wrong. We should look up the
* symbol declaration info.
*/
|
|
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Linus Torvalds explains:
On Mon, Aug 29, 2011 at 12:45 PM, Pekka Enberg <penberg@kernel.org> wrote:
> However, i'm not 100% sure that's sufficient. Is OP_CAST always zero-extend
> or do we need to check for something specific here?
OP_CAST is always a zero-extend, OP_SCAST is a sign-extending one.
(Of course, they may be *truncating* casts too, which don't need to
generate any code on most architectures).
OP_PTRCAST should act as OP_CAST.
NOTE! The casting is dubious. We only have a single OP_FPCAST, for
example, and that's just broken. Right now "OP_FPCAST" means that the
*source* was a FP value. But if we cast *to* a FP value, it ends up
showing up as OP_[S]CAST, which is just bogus. The FPCAST should be
for any FP operation (to or from or both), and then the FPCAST logic
would have to decide how it handles it.
The FP support in general is pretty weak. The kernel doesn't do FP, I
never really cared about it.
This patch fixes comparison operator code generation. For example, this C code
int sete(int x, int y)
{
return x == y;
}
is translated as follows:
Before:
0000000000000000 <sete>:
0: 31 c9 xor %ecx,%ecx
2: 39 f7 cmp %esi,%edi
4: b8 ff ff ff ff mov $0xffffffff,%eax
9: 0f 45 c1 cmovne %ecx,%eax
c: c3 retq
After:
0000000000000000 <sete>:
0: 39 f7 cmp %esi,%edi
2: 0f 94 c0 sete %al
5: 0f b6 c0 movzbl %al,%eax
8: c3 retq
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
|
|
Just code movement, no other changes.
|
|
testcase...
extern int f(int a, int b);
int foo(int x)
{
int y;
y = f(x + 1, x + 2);
y += f(x + 11, x + 22);
return y;
}
|
|
|
|
Simply reference used value directly.
|
|
You can get module dump with:
./sparse-llvm foo.c | llvm-dis
so lets just kill debugging code that's used for the same thing.
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
LLVM works with SSA form just fine so there's absolutely no reason to convert
the linearized IR into normal form before passing it to LLVM.
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
int foo(int *x)
{
int y;
y = *x;
y += 12;
return y;
}
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
testcase:
int foo(int x)
{
switch (x) {
case 1:
return 11;
case 2:
return 22;
default:
return 33;
}
return 44;
}
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
It gets the code a bit farther, with the following test case:
int foo(int x)
{
if (x > 0xffff)
x++;
else
x--;
return x;
}
* run with
./sparse-llvm hello.c | llvm-dis
for an IMO more useful disassembly than via 'llc'
* add 'priv' to struct basic_block
* run a first pass through the BB's, creating LLVMBasicBlockRef's and assigning
them to bb->priv
* comment out unssa() call, and implement OP_PHI and OP_PHISOURCE, which LLVM
directly supports.
* remove '%' prefix from PSEUDO_REG names, as it was redundant and made
llvm-dis output ugly
* implement support for conditional and unconditional branches (OP_BR)
* implement OP_COPY. a possibly better implementation would be a single-source
LLVMBuildPhi
[ penberg@kernel.org: minor cleanups ]
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
We need OP_CAST before we can actually generate code for them.
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
This is the first commit to implementing a LLVM backend for sparse using the
LLVM C bindings.
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|