//===- ConstantProp.cpp - Code to perform Simple Constant Propagation -----===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements calling convention rewrite for Native Client to ensure
// compatibility between pnacl and gcc generated code when calling
// ppapi interface functions.
//===----------------------------------------------------------------------===//
// Major TODOs:
// * dealing with vararg
// (We shoulf exclude all var arg functions and calls to them from rewrites)
#define DEBUG_TYPE "naclcc"
#include "llvm/Argument.h"
#include "llvm/Attributes.h"
#include "llvm/Constant.h"
#include "llvm/DataLayout.h"
#include "llvm/Instruction.h"
#include "llvm/Instructions.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Function.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/InstIterator.h"
#include "llvm/Target/TargetLibraryInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Transforms/Scalar.h"
#include <vector>
using namespace llvm;
namespace llvm {
cl::opt<bool> FlagEnableCcRewrite(
"nacl-cc-rewrite",
cl::desc("enable NaCl CC rewrite"));
}
namespace {
// This represents a rule for rewiriting types
struct TypeRewriteRule {
const char* src; // type pattern we are trying to match
const char* dst; // replacement type
const char* name; // name of the rule for diagnosis
};
// Note: all rules must be well-formed
// * parentheses must match
// * TODO: add verification for this
// Legend:
// s(): struct (also used for unions)
// c: char (= 8 bit int) (only allowed for src)
// i: 32 bit int
// l: 64 bit int
// f: 32 bit float
// d: 64 bit float (= double)
// p: untyped pointer (only allowed for src)
// P(): typed pointer (currently not used, only allowed for src)
// F: generic function type (only allowed for src)
// The X8664 Rewrite rules are also subject to
// register constraints, c.f.: section 3.2.3
// http://www.x86-64.org/documentation/abi.pdf
// (roughly) for X8664: up to 2 regs per struct can be used for struct passsing
// and up to 2 regs for struct returns
// The rewrite rules are straight forward except for: s(iis(d)) => ll
// which would be straight forward if the frontend had lowered the union inside
// of PP_Var to s(l) instead of s(d), yielding: s(iis(l)) => ll
TypeRewriteRule ByvalRulesX8664[] = {
{"s(iis(d))", "ll", "PP_Var"},
{"s(pp)", "l", "PP_ArrayOutput"},
{"s(ppi)", "li", "PP_CompletionCallback"},
{0, 0, 0},
};
TypeRewriteRule SretRulesX8664[] = {
// Note: for srets, multireg returns are modeled as struct returns
{"s(iis(d))", "s(ll)", "PP_Var"},
{"s(ff)", "d", "PP_FloatPoint"},
{"s(ii)", "l", "PP_Point" },
{"s(pp)", "l", "PP_ArrayOutput"},
{0, 0, 0},
};
// for ARM: up to 4 regs can be used for struct passsing
// and up to 2 float regs for struct returns
TypeRewriteRule ByvalRulesARM[] = {
{"s(iis(d))", "ll", "PP_Var"},
{"s(ppi)", "iii", "PP_CompletionCallback" },
{"s(pp)", "ii", "PP_ArrayOutput"},
{0, 0, 0},
};
TypeRewriteRule SretRulesARM[] = {
// Note: for srets, multireg returns are modeled as struct returns
{"s(ff)", "s(ff)", "PP_FloatPoint"},
{0, 0, 0},
};
// Helper class to model Register Usage as required by
// the x86-64 calling conventions
class RegUse {
uint32_t n_int_;
uint32_t n_float_;
public:
RegUse(uint32_t n_int=0, uint32_t n_float=0) :
n_int_(n_int), n_float_(n_float) {}
static RegUse OneIntReg() { return RegUse(1, 0); }
static RegUse OnePointerReg() { return RegUse(1, 0); }
static RegUse OneFloatReg() { return RegUse(0, 1); }
RegUse operator+(RegUse other) const {
return RegUse(n_int_ + other.n_int_, n_float_ + other.n_float_); }
RegUse operator-(RegUse other) const {
return RegUse(n_int_ - other.n_int_, n_float_ - other.n_float_); }
bool operator==(RegUse other) const {
return n_int_ == other.n_int_ && n_float_ == other.n_float_; }
bool operator!=(RegUse other) const {
return n_int_ != other.n_int_ && n_float_ != other.n_float_; }
bool operator<=(RegUse other) const {
return n_int_ <= other.n_int_ && n_float_ <= other.n_float_; }
bool operator<(RegUse other)