aboutsummaryrefslogtreecommitdiffstats
path: root/sparse-llvm.c
AgeCommit message (Collapse)AuthorFilesLines
2021-03-08phi-sources can only have a single user (or none)Luc Van Oostenryck1-2/+0
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>
2020-11-21add a new instruction for label-as-valueLuc Van Oostenryck1-0/+8
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>
2020-10-23llvm: fix crash with llvm-11 / use real phi-nodesLuc Van Oostenryck1-46/+29
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>
2018-08-25Merge branch 'ssa' into tipLuc Van Oostenryck1-0/+6
* do 'classical' SSA conversion (via the iterated dominance frontier). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-07-01add PSEUDO_UNDEF & undef_pseudo()Luc Van Oostenryck1-0/+6
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>
2018-06-30Merge branch 'cast-optim' into tipLuc Van Oostenryck1-0/+4
* optimize away OP_UTPTR & OP_PTRTU which are nops.
2018-06-29cast: optimize away casts to/from pointersLuc Van Oostenryck1-0/+4
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>
2018-06-28bool: remove OP_{AND,OR}_BOOL instructionsLuc Van Oostenryck1-24/+0
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>
2018-06-23cast: specialize integer castsLuc Van Oostenryck1-4/+7
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>
2018-06-23cast: specialize cast from pointersLuc Van Oostenryck1-6/+19
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>
2018-06-23cast: specialize casts from unsigned to pointersLuc Van Oostenryck1-0/+1
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>
2018-06-23cast: specialize floats to integer conversionLuc Van Oostenryck1-1/+7
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>
2018-06-23cast: specialize FPCAST into [USF]CVTFLuc Van Oostenryck1-4/+12
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>
2018-06-21ptrlist: remove the now unneeded FOR_EACH_PTR_NOTAG()Luc Van Oostenryck1-2/+2
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>
2018-03-11llvm: fix typo for constant addressesLuc Van Oostenryck1-1/+2
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>
2018-03-01IR: let .cond unionize with .src and not .targetLuc Van Oostenryck1-1/+1
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>
2018-03-01IR: remove now unused OP_LNOP & OP_SNOPLuc Van Oostenryck1-6/+0
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>
2018-02-20no need for signed & unsigned multiplicationLuc Van Oostenryck1-5/+1
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>
2018-02-17llvm: initialize at declaration timeLuc Van Oostenryck1-12/+5
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>
2018-02-17llvm: use list_size() to count the numbers of argumentsLuc Van Oostenryck1-7/+2
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>
2018-01-08add OP_SETFVALLuc Van Oostenryck1-4/+12
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>
2018-01-07Merge branches 'fmax-warnings', 'funsigned-char', ↵Luc Van Oostenryck1-35/+25
'testcase-fix-missing-return', 'type-as-first-class', 'llvm-zero-init' and 'llvm-prototype' into tip
2017-12-28llvm: default init of arrays & structsLuc Van Oostenryck1-0/+6
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>
2017-12-28llvm: simplify emit of null pointersLuc Van Oostenryck1-4/+6
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>
2017-12-27llvm: add declares for function prototypesLuc Van Oostenryck1-1/+4
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>
2017-12-27llvm: use LLVMModuleRef for get_sym_value()Luc Van Oostenryck1-8/+8
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>
2017-12-27llvm: fix: previous function ref MUST be reusedLuc Van Oostenryck1-23/+2
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>
2017-11-18add support of floating-point specific arithmetic opsLuc Van Oostenryck1-17/+20
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>
2017-11-18fix support of floating-point compareLuc Van Oostenryck1-12/+15
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>
2017-11-17llvm: only compare void pointersLuc Van Oostenryck1-0/+4
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>
2017-11-17llvm: add support for float initializerLuc Van Oostenryck1-0/+3
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: warn instead of assert on global initsLuc Van Oostenryck1-1/+6
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>
2017-11-17llvm: gracefully catch impossible type/valueLuc Van Oostenryck1-2/+9
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>
2017-11-17llvm: give names easier to debugLuc Van Oostenryck1-3/+3
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>
2017-11-17llvm: cleanup of output_[ptr]cast()Luc Van Oostenryck1-27/+12
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: add support for cast from floatsLuc Van Oostenryck1-1/+9
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: add support for OP_FPCASTLuc Van Oostenryck1-1/+21
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: fix type of bitfieldsLuc Van Oostenryck1-0/+2
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: fix get value from non-anonymous symbolLuc Van Oostenryck1-9/+2
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: fix get value from initialized symbolLuc Van Oostenryck1-14/+13
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: add support for restricted typesLuc Van Oostenryck1-0/+1
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: fix mutated OP_[PTR]CASTLuc Van Oostenryck1-6/+4
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: fix mutated OP_PHISOURCELuc Van Oostenryck1-1/+1
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: fix mutated OP_SWITCHLuc Van Oostenryck1-1/+1
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: fix mutated OP_SELLuc Van Oostenryck1-3/+3
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: fix mutated OP_RETLuc Van Oostenryck1-3/+1
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: fix mutating function pointerLuc Van Oostenryck1-6/+27
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: take care of degenerated rvaluesLuc Van Oostenryck1-2/+12
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: fix variadic calls with constantsLuc Van Oostenryck1-1/+5
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>
2017-11-17llvm: let pseudo_to_value() directly use the typeLuc Van Oostenryck1-21/+21
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: make value_to_ivalue() more flexibleLuc Van Oostenryck1-5/+10
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: make value_to_pvalue() more flexibleLuc Van Oostenryck1-3/+12
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: fix OP_SWITCH has no targetLuc Van Oostenryck1-3/+1
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: add support for OP_SWITCH with a rangeLuc Van Oostenryck1-10/+7
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: give a name to all valuesLuc Van Oostenryck1-13/+20
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: make pseudo_name() more flexibleLuc Van Oostenryck1-11/+6
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: fix type of switch constantsLuc Van Oostenryck1-1/+1
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>
2017-11-17llvm: variadic functions are not being marked as suchLuc Van Oostenryck1-1/+1
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>
2017-11-17llvm: adjust OP_RET's typeLuc Van Oostenryck1-0/+1
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: give correct type to binopsLuc Van Oostenryck1-0/+30
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>
2017-11-17llvm: fix type in comparison with an address constantLuc Van Oostenryck1-2/+1
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>
2017-11-17llvm: fix pointer/float mixup in comparisonsLuc Van Oostenryck1-2/+15
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>
2017-11-17llvm: ignore OP_INLINED_CALLLuc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: add support for OP_SETVAL with labelsLuc Van Oostenryck1-0/+3
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: add support for OP_SETVAL with floatsLuc Van Oostenryck1-1/+18
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: add support for OP_NEGLuc Van Oostenryck1-2/+15
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>
2017-11-17llvm: fix output_op_[ptr]cast()Luc Van Oostenryck1-5/+35
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>
2017-11-17llvm: fix output_op_store() which modify its operandLuc Van Oostenryck1-4/+2
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>
2017-11-17llvm: fix translation of PSEUDO_VALs into a ValueRefsLuc Van Oostenryck1-1/+30
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>
2017-11-17llvm: fix test of floating-point typeLuc Van Oostenryck1-25/+17
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: extract get_sym_value() from pseudo_to_value()Luc Van Oostenryck1-47/+53
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: avoid useless temp variableLuc Van Oostenryck1-5/+2
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: give a name to call's return valuesLuc Van Oostenryck1-1/+6
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>
2017-11-17llvm: give arguments a nameLuc Van Oostenryck1-0/+12
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>
2017-11-17llvm: use pseudo_list_size() instead of open coding itLuc Van Oostenryck1-4/+1
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: reduce scope of 'bb_nr'Luc Van Oostenryck1-2/+1
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: remove unneeded function::typeLuc Van Oostenryck1-3/+3
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: remove unneeded 'generation'Luc Van Oostenryck1-11/+2
It's not needed here since there is no recursive access to BBs. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17llvm: remove unneeded arg 'module'Luc Van Oostenryck1-37/+37
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-05-15use -fmem-report to report allocation statsLuc Van Oostenryck1-0/+1
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-03-06split OP_BR between unconditional & conditional: OP_CBRLuc Van Oostenryck1-11/+14
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>
2017-02-13llvm: remove unneeded OP_COPY supportLuc Van Oostenryck1-29/+1
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>
2017-02-13llvm: fix typing when comparing to a constantLuc Van Oostenryck1-17/+32
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>
2015-06-14sparse, llvm: compile: skip function prototypes to avoid SIGSEGVAzat Khuzhin1-0/+11
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>
2013-05-27Fix result type of relational and logical operatorsXi Wang1-11/+18
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>
2013-05-21sparse, llvm: die if errorXi Wang1-1/+4
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>
2013-05-21sparse, llvm: set more data attributesXi Wang1-0/+6
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>
2013-05-21sparse, llvm: fix struct name generationXi Wang1-6/+3
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>
2013-05-21sparse, llvm: cache symbol_type() resultXi Wang1-1/+10
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>
2013-05-21sparse, llvm: fix array sizeXi Wang1-1/+3
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>
2013-05-21sparse, llvm: use LLVM_DEFAULT_TARGET_TRIPLEXi Wang1-1/+5
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>
2013-05-20sparse, llvm: Use LLVM_HOSTTRIPLEPekka Enberg1-1/+1
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>
2013-05-19sparse, llvm: set target specificationXi Wang1-3/+53
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>
2013-05-19sparse, llvm: improve pointer arithmetic handlingXi Wang1-12/+26
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>
2013-05-19sparse, llvm: base load/store address type on insn_symbol_type()Jonathan Neuschäfer1-3/+4
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>
2013-05-19sparse, llvm: de-duplicate load/store address calculation codeJonathan Neuschäfer1-17/+14
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>
2013-05-19sparse, llvm: Fix resulting type of store address calculationsJonathan Neuschäfer1-1/+1
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>
2013-05-18sparse, llvm: simplify function generationXi Wang1-163/+12
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>
2013-05-18sparse, llvm: fix phi generationXi Wang1-91/+40
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>
2012-10-10sparse, llvm: Fix type of loaded valuesJonathan Neuschäfer1-1/+1
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>
2012-08-19sparse, llvm: convert the condition of branch/select to boolJonathan Neuschäfer1-2/+11
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>
2012-08-19sparse, llvm: Fix 'void' return type code generationPekka Enberg1-2/+10
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>
2012-08-19sparse, llvm: 'Verify' the LLVM module before writing itJonathan Neuschäfer1-0/+3
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>
2012-08-05sparse, llvm: Fix SIGSEGV for extern symbolsPekka Enberg1-0/+8
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>
2012-06-09sparse, llvm: Fix global string access code generationPekka Enberg1-1/+7
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>
2012-06-08sparse, llvm: Fix string initializer code generationPekka Enberg1-0/+6
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>
2012-06-08sparse, llvm: Simplify output_data() type logicPekka Enberg1-1/+1
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>
2012-02-04sparse, llvm: Fix varargs functionsBenjamin Herrenschmidt1-2/+2
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>
2011-12-21sparse, llvm: Use LLVMInt1Type() in sym_basetype_type()Pekka Enberg1-0/+3
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>
2011-11-23sparse, llvm: Fix loops, by properly handling OP_PHI forward referencesJeff Garzik1-7/+77
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>
2011-11-22sparse, llvm: FP comparison op code generationPekka Enberg1-2/+27
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>
2011-11-22sparse, llvm: Simplify comparison op code generationPekka Enberg1-33/+23
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>
2011-11-22sparse, llvm: More comparison ops code generationPekka Enberg1-4/+4
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>
2011-11-22sparse, llvm: OP_SET_B and OP_SET_A code generationPekka Enberg1-2/+2
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>
2011-11-22sparse, llvm: Pointer cast code generationPekka Enberg1-1/+19
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>
2011-11-21sparse, llvm: Fix 'extern' symbol code generationPekka Enberg1-1/+2
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>
2011-11-21sparse, llvm: Fix symbol initializer code generationPekka Enberg1-2/+4
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>
2011-11-19sparse, llvm: Function pointer code generationPekka Enberg1-2/+52
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>
2011-10-28sparse, llvm: Add support for union typesPekka Enberg1-0/+20
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>
2011-10-25sparse, llvm: Add support for array typesPekka Enberg1-0/+17
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>
2011-10-25sparse, llvm: Fix symbol_type() for bitfields and enumsPekka Enberg1-0/+2
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>
2011-10-24sparse, llvm: Fix struct code generationPekka Enberg1-23/+27
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>
2011-10-24sparse, llvm: Use new LLVM type system API for structsPekka Enberg1-2/+13
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>
2011-10-24sparse, llvm: Fix 'void *' pointer code generationPekka Enberg1-3/+1
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>
2011-09-28sparse, llvm: Add support for logical opsPekka Enberg1-4/+19
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>
2011-09-09sparse, llvm: Add support for symbol initializersPekka Enberg1-2/+11
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-09-07sparse, llvm: Add support for struct typesPekka Enberg1-2/+53
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-31sparse, llvm: Fix code generation for 'long double' data typePekka Enberg1-0/+3
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-31sparse, llvm: support OP_STOREJeff Garzik1-1/+31
testcase: int foo(int *addr_i, int x) { *addr_i = x; return x; }
2011-08-30sparse, llvm: move OP_COPY support to separate function. Add FP support.Jeff Garzik1-12/+30
2011-08-30sparse, llvm: store module-local functions on function reference listJeff Garzik1-1/+9
Fixes testcase: int sum(int x, int y) { return x + y; } int main(int argc, char *argv[]) { return sum(1, 2); }
2011-08-30llvm, sparse: Fix symbol_is_fp_type() goofPekka Enberg1-1/+2
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-30Merge branch 'master' of github.com:penberg/sparse-llvmPekka Enberg1-7/+27
Conflicts: sparse-llvm.c
2011-08-30sparse, llvm: Fix pseudo_type() for PSEUDO_ARGPekka Enberg1-4/+4
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-30sparse, llvm: create helper for obtaining instruction's typeJeff Garzik1-7/+27
Use with PSEUDO_VAL. Also, remove needless braces around PSEUDO_ARG.
2011-08-30sparse, llvm: Fix code generation for castsPekka Enberg1-6/+10
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-30Revert "sparse, llvm: Don't redefine module local functions"Pekka Enberg1-5/+0
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. */
2011-08-30sparse, llvm: Don't redefine module local functionsPekka Enberg1-0/+5
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-30sparse, llvm: Fix PSEUDO_OP code generationPekka Enberg1-21/+21
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-29sparse, llvm: Fix OP_CAST to use zero-extendPekka Enberg1-1/+1
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>
2011-08-29sparse, llvm: Cleanup output_data()Pekka Enberg1-3/+5
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-29sparse, llvm: Code generation for string constantsPekka Enberg1-6/+48
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-28sparse, llvm: move OP_CAST code to separate func. support FP casts.Jeff Garzik1-12/+20
2011-08-27sparse, llvm: move OP_PHI code from switch statement to separate functionJeff Garzik1-31/+35
Just code movement, no other changes.
2011-08-27sparse, llvm: implement OP_CALLJeff Garzik1-1/+157
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; }
2011-08-27sparse, llvm: replace FIXME comment with assert(), following existing styleJeff Garzik1-2/+2
2011-08-27sparse-llvm OP_PHISOURCE: replace copy with target=src pointer operationJeff Garzik1-12/+3
Simply reference used value directly.
2011-08-27sparse, llvm: Kill debugging codePekka Enberg1-4/+0
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>
2011-08-27sparse, llvm: Kill ifdef'd unssa() callPekka Enberg1-4/+0
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>
2011-08-27sparse, llvm: Bitwise not operator codegenPekka Enberg1-1/+14
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-27sparse, llvm: Floating point support for binopsPekka Enberg1-24/+70
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-27sparse-llvm: OP_LOADJeff Garzik1-1/+29
int foo(int *x) { int y; y = *x; y += 12; return y; } Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-27sparse-llvm: OP_SWITCHJeff Garzik1-5/+47
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>
2011-08-27sparse-llvm: OP_SELJeff Garzik1-1/+14
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-27sparse, llvm: if-else code generationJeff Garzik1-12/+86
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>
2011-08-25sparse, llvm: Implement OP_CASTPekka Enberg1-3/+12
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-25sparse, llvm: Implement some binary comparison opsPekka Enberg1-4/+30
We need OP_CAST before we can actually generate code for them. Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-25sparse, llvm: Add support for more binary opsPekka Enberg1-13/+15
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-25sparse, llvm: Implement OP_ADDPekka Enberg1-22/+69
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-25sparse, llvm: Add output_op_binary() stubPekka Enberg1-0/+91
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-25sparse, llvm: Introduce 'struct function' to clean up codePekka Enberg1-18/+23
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-25sparse, llvm: Add support for OP_RET/PSEUDO_ARGPekka Enberg1-10/+15
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-23sparse, llvm: OP_RET/PSEUDO_VAL code generationPekka Enberg1-20/+39
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-23sparse, llvm: Add switch statement to output_insn()Pekka Enberg1-8/+62
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-23llvm, sparse: Separate entry and exit basic blocksPekka Enberg1-6/+14
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-23sparse, llvm: Fix global variable initializationPekka Enberg1-2/+11
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-23sparse, llvm: Initial commitPekka Enberg1-0/+185
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>